mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 18:50:11 +00:00
Compare commits
292 Commits
couchdb-ob
...
mobile_ges
Author | SHA1 | Date | |
---|---|---|---|
1162b0c88c | |||
eb4c7e318e | |||
ad3f055747 | |||
23d0b50593 | |||
73079e109c | |||
ce80806917 | |||
ddf519c17e | |||
e8739ede0e | |||
8101fd7a20 | |||
820960f879 | |||
6f130ae48c | |||
4e44571819 | |||
8920b5454b | |||
989819c7bd | |||
f5da8252af | |||
00a8aea6ea | |||
8072e829ad | |||
e866ddb9fd | |||
4fa29d30f5 | |||
c394151c46 | |||
db1b76413c | |||
c8b02d355f | |||
7c110ee8af | |||
49213f550f | |||
678d11832c | |||
447ae3f20b | |||
7288db1908 | |||
908fbdbf73 | |||
052a359738 | |||
f9be00a70f | |||
d1055f0839 | |||
0b7ab75512 | |||
9d1841db55 | |||
50d10639e1 | |||
5a9619ce26 | |||
42b7427816 | |||
a1b37b1269 | |||
8a5c61e2e6 | |||
c8ca1deb9b | |||
5be6e90388 | |||
814b04858a | |||
aedbd3bd9b | |||
aa4dbf7062 | |||
5b95574673 | |||
2295be5e35 | |||
0ac6caa823 | |||
5e1dd04e6d | |||
29df378851 | |||
8511c957a0 | |||
f4efc79539 | |||
3926d6f617 | |||
d65e0f820f | |||
021d105fd0 | |||
7ffbc9ad2f | |||
24fe419be4 | |||
90f62b92a5 | |||
5a991076ea | |||
3e2c3f913b | |||
a45b09277e | |||
bdf3e4d8a3 | |||
e4a2904213 | |||
f1d4e36c02 | |||
b3792c21be | |||
54bf39344a | |||
683b3f7511 | |||
510e7d1261 | |||
63b41d796a | |||
80a91970f6 | |||
f0c64b6b92 | |||
48136c2265 | |||
1961adf8d6 | |||
8c4c65241a | |||
67cb5f8077 | |||
bb2f086623 | |||
a0169ad158 | |||
6e172359b4 | |||
d33678276c | |||
1cbca41c53 | |||
a27083c28c | |||
def5e17bb8 | |||
b8b9721ddc | |||
f80266b23f | |||
9a3009f327 | |||
2542255342 | |||
89bfa54563 | |||
793c99ac2f | |||
39bd292886 | |||
e8bc9ecc1a | |||
0fa330adff | |||
9cd57614e4 | |||
d80c359a86 | |||
07d0706cd1 | |||
fd5a911d50 | |||
c71f1fe447 | |||
cd46dab5c1 | |||
e1858bf0ae | |||
7542c6d49a | |||
13b66cd215 | |||
aca06c6007 | |||
5184e08a5b | |||
69c6d4bd26 | |||
6a2bdd103b | |||
76c4b96683 | |||
44ed4e0e0d | |||
e96d3e3738 | |||
039d692e4c | |||
ee608cc4a4 | |||
da8eb334e3 | |||
67592def90 | |||
3484b315cf | |||
1fbbf355f4 | |||
b1e1e85bbd | |||
c4dd4f5c45 | |||
9fec73da14 | |||
23048f0df9 | |||
dfe3409a98 | |||
5c3fe78bd5 | |||
eb69e02ce3 | |||
17e2da2d2c | |||
03db1b3623 | |||
5c23daa5ff | |||
056b3f61ce | |||
a0dc3da8fb | |||
48f345a46b | |||
2cf7f6794c | |||
889a5c6ea9 | |||
5502009127 | |||
cb41be7922 | |||
2997f2a261 | |||
52b8720d37 | |||
bb8c8a75ab | |||
d10c56f732 | |||
1f7d0427b7 | |||
caf1e3aea9 | |||
3031579a62 | |||
00aa7ce0c2 | |||
cac97401c6 | |||
7b371327e6 | |||
113d1c909f | |||
63a99f26f6 | |||
7ca15a9de2 | |||
7ac1d2458a | |||
0bc4f2dc6e | |||
dcd7d61c9a | |||
7c17581659 | |||
0a39984c4f | |||
a146185bd2 | |||
0b635afcf7 | |||
f46a0853b9 | |||
66c81ce3d6 | |||
6b65ae77e7 | |||
66408eeec8 | |||
3d524d7572 | |||
9b922913a0 | |||
560a2e035e | |||
eca52a8ca6 | |||
2983ebb2c6 | |||
25e8bb44d2 | |||
1a8eece90f | |||
85658d3d1f | |||
ddce0f371d | |||
495cd06ed5 | |||
1624866656 | |||
2d1aa65d63 | |||
c333a2e70a | |||
906354764b | |||
12ec293f3d | |||
bdf8b4d3f1 | |||
6e60088b11 | |||
97bf530b1d | |||
18348476c6 | |||
7e35e55f0b | |||
28a2a5b92a | |||
d262520594 | |||
7cc14a195b | |||
84b9e4d781 | |||
52e0476d24 | |||
86340623f7 | |||
356fa73c91 | |||
a073ef69ac | |||
3c6c420023 | |||
21964fe68e | |||
62714bb97c | |||
2a4943f584 | |||
e32403a75f | |||
b0c42c12b7 | |||
621ccc25ec | |||
617df739ee | |||
6e43a92191 | |||
1d7a0fa48d | |||
30c530178a | |||
3d0795cde3 | |||
c85a3787c0 | |||
066258ab83 | |||
ddc2295ec3 | |||
011e6fc512 | |||
91bd58215a | |||
b37ee19fbc | |||
2355d354b3 | |||
200c6e49fc | |||
a89f9eed42 | |||
7993e4c03f | |||
b592b89dc8 | |||
d115166dde | |||
d176f9f811 | |||
143e3eeb6c | |||
b3bc8b6876 | |||
1f7ba70ad7 | |||
7aba3b6672 | |||
926b3d075c | |||
827cb27f28 | |||
0842f464db | |||
56e51ea32a | |||
dcdafbaebf | |||
f98915cddd | |||
4e6c307684 | |||
ce6d74390e | |||
6e406fd060 | |||
2614427e0e | |||
272c6bca97 | |||
0d7387080d | |||
1e2e20b145 | |||
488829a20c | |||
85c7a36e25 | |||
d99b4d75d8 | |||
15a88967d0 | |||
6e6fbe0d65 | |||
180e5f14ae | |||
e9314898d2 | |||
ce75d19480 | |||
a9dd1f9828 | |||
4b5540830b | |||
ee35976c92 | |||
54b6cd1100 | |||
0f89e98a71 | |||
6f07a21bb8 | |||
f3678d9d52 | |||
9a7bbd92bd | |||
edcafc5835 | |||
7d09df9a85 | |||
b00eee00fc | |||
c0d83f9395 | |||
be757066f5 | |||
885433390e | |||
687f810475 | |||
137a60f510 | |||
46d5a1431f | |||
404d02ec23 | |||
eec955317a | |||
67890a7298 | |||
dd457f26c6 | |||
85c6bda5c9 | |||
b7b5f87002 | |||
b0c5d807e7 | |||
4d4776e0ef | |||
61e1aeb1d8 | |||
9caa603a65 | |||
5c99e469d5 | |||
4d9dc3624b | |||
d3ae4b729f | |||
30bed434fe | |||
3e4ae4d38d | |||
7414275a85 | |||
fcb0033864 | |||
f079471a18 | |||
1fb1174c0a | |||
635e1eda69 | |||
40d53f941f | |||
684a0e88a2 | |||
30a4f15330 | |||
dfd08000f1 | |||
82c8d26264 | |||
bd236e1cb1 | |||
e47a36e799 | |||
30efec0090 | |||
b9371ea03d | |||
7974f33781 | |||
cdcaedc8dd | |||
07ef4dfe8a | |||
342be0822f | |||
5c56484889 | |||
2b4162c0be | |||
3704d64560 | |||
24fae72492 | |||
79fb6eabd9 | |||
1ddb00c8d6 | |||
8a0b77ec5c | |||
2fc447e16f | |||
d828bf59f9 | |||
d8806f14aa | |||
0c6a9ca857 | |||
b40494ac95 |
@ -14,7 +14,7 @@
|
||||
"platform/features/imagery",
|
||||
"platform/features/layout",
|
||||
"platform/features/pages",
|
||||
"platform/features/plot",
|
||||
"platform/features/plot-reborn",
|
||||
"platform/features/scrolling",
|
||||
"platform/features/events",
|
||||
"platform/forms",
|
||||
|
@ -8,3 +8,7 @@ deployment:
|
||||
branch: search
|
||||
heroku:
|
||||
appname: openmctweb-staging-un
|
||||
openmctweb-staging-deux:
|
||||
branch: mobile
|
||||
heroku:
|
||||
appname: openmctweb-staging-deux
|
||||
|
@ -23,6 +23,7 @@
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title></title>
|
||||
<script type="text/javascript"
|
||||
src="platform/framework/lib/require.js"
|
||||
|
@ -82,6 +82,11 @@
|
||||
"templateUrl": "templates/menu-arrow.html",
|
||||
"uses": [ "action" ],
|
||||
"gestures": [ "menu" ]
|
||||
},
|
||||
{
|
||||
"key": "back-arrow",
|
||||
"uses": [ "type", "action" ],
|
||||
"templateUrl": "templates/back-arrow.html"
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
|
28
platform/commonUI/browse/res/templates/back-arrow.html
Normal file
28
platform/commonUI/browse/res/templates/back-arrow.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!-- Back Arrow Icon used on mobile-->
|
||||
<a ng-controller="BrowseController"
|
||||
class='type-icon icon ui-symbol s-back'
|
||||
ng-class="checkRoot(); atRoot ? 'hidden' : ''"
|
||||
ng-click='backArrow()'>{
|
||||
</a>
|
@ -20,22 +20,23 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="BrowseObjectController">
|
||||
<div class="object-browse-bar bar abs">
|
||||
<div class="items-select left abs">
|
||||
<div class="object-browse-bar bar l-flex">
|
||||
<div class="items-select left">
|
||||
<mct-representation key="'back-arrow'" class="l-back"></mct-representation>
|
||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<div class="btn-bar right abs">
|
||||
<mct-representation key="'action-group'"
|
||||
mct-object="domainObject"
|
||||
parameters="{ category: 'view-control' }">
|
||||
</mct-representation>
|
||||
|
||||
<div class="btn-bar right">
|
||||
<mct-representation key="'switcher'"
|
||||
mct-object="domainObject"
|
||||
ng-model="representation">
|
||||
</mct-representation>
|
||||
<!-- Temporarily, on mobile, the action buttons are hidden-->
|
||||
<mct-representation key="'action-group'"
|
||||
mct-object="domainObject"
|
||||
parameters="{ category: 'view-control' }"
|
||||
class="mobile-hide">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -19,36 +19,40 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div content="jquery-wrapper" class="abs holder-all browse-mode">
|
||||
|
||||
<div class="abs holder-all browse-mode" ng-controller="BrowseController">
|
||||
<mct-include key="'topbar-browse'"></mct-include>
|
||||
<div class="holder browse-area s-browse-area abs" ng-controller="BrowseController">
|
||||
<div class="holder browse-area s-browse-area abs browse-wrapper" ng-class="treeClass ? 'browse-showtree' : 'browse-hidetree'">
|
||||
<mct-split-pane class='contents abs' anchor='left'>
|
||||
<div
|
||||
class='split-pane-component treeview pane left'
|
||||
>
|
||||
<mct-representation key="'create-button'" mct-object="navigatedObject">
|
||||
</mct-representation>
|
||||
<div class='holder search-holder abs'
|
||||
ng-class="{active: treeModel.search}">
|
||||
<mct-representation key="'search'"
|
||||
mct-object="domainObject"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class='holder tree-holder abs'
|
||||
ng-hide="treeModel.search">
|
||||
<mct-representation key="'tree'"
|
||||
mct-object="domainObject"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class='split-pane-component treeview pane left'>
|
||||
<div class="holder abs l-mobile">
|
||||
<mct-representation key="'create-button'" mct-object="navigatedObject">
|
||||
</mct-representation>
|
||||
<div class='holder search-holder abs'
|
||||
ng-class="{active: treeModel.search}">
|
||||
<mct-representation key="'search'"
|
||||
mct-object="domainObject"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class='tree-holder abs mobile-tree-holder'
|
||||
ng-hide="treeModel.search">
|
||||
<mct-representation key="'tree'"
|
||||
mct-object="domainObject"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mct-splitter></mct-splitter>
|
||||
<div class='split-pane-component items pane'>
|
||||
<div class='holder abs' id='content-area'>
|
||||
|
||||
<mct-splitter class="mobile-hide"></mct-splitter>
|
||||
|
||||
<div class='split-pane-component items pane right-repr'>
|
||||
<div class='holder abs l-mobile' id='content-area'>
|
||||
<mct-representation mct-object="navigatedObject" key="'browse-object'">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="key-properties ui-symbol icon mobile-menu-icon desktop-hide" ng-click="treeSlide()">m</div>
|
||||
</div>
|
||||
</mct-split-pane>
|
||||
</div>
|
||||
|
@ -19,11 +19,11 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='object-header'>
|
||||
<span class="label s-label">
|
||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<div class='object-header object-header-mobile'>
|
||||
<span class='type-icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<!--span class='type-name mobile-important-hide'>{{type.getName()}}</span-->
|
||||
<span class="l-elem-wrapper l-flex">
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='type-name'>{{type.getName()}}</span>
|
||||
<span class='title-label'>{{model.name}}</span>
|
||||
<mct-representation key="'menu-arrow'" mct-object='domainObject'></mct-representation>
|
||||
</span>
|
||||
|
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<div class='object-holder abs vscroll'>
|
||||
<mct-representation key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
@ -21,31 +21,27 @@
|
||||
-->
|
||||
<!-- For selected, add class 'selected' to outer div -->
|
||||
<div class='item grid-item' ng-click='action.perform("navigate")'>
|
||||
<div class="contents abs">
|
||||
<div class='contents abs'>
|
||||
<div class='top-bar bar abs'>
|
||||
<div class='left abs'>
|
||||
<mct-include key="_checkbox"></mct-include>
|
||||
</div>
|
||||
<div class='right abs'>
|
||||
<div class='ui-symbol icon l-icon-alert'></div>
|
||||
<div class='ui-symbol icon profile' title="Shared">P</div>
|
||||
</div>
|
||||
<div class='ui-symbol profile' title='Shared'>O</div>
|
||||
<mct-representation class="desktop-hide" key="'info-button'" mct-object="domainObject"></mct-representation>
|
||||
</div>
|
||||
<div class='item-main abs'>
|
||||
<div class='ui-symbol icon lg item-type'>
|
||||
{{type.getGlyph()}}
|
||||
<span
|
||||
class="ui-symbol icon l-icon-link" title="This object is a link"
|
||||
class="ui-symbol l-icon-link" title="This object is a link"
|
||||
ng-show="location.isLink()"
|
||||
></span>
|
||||
</div>
|
||||
<div class='ui-symbol icon abs item-open'>}</div>
|
||||
<div class='ui-symbol abs item-open'>}</div>
|
||||
</div>
|
||||
<div class='bottom-bar bar abs'>
|
||||
<div class='title'>{{model.name}}</div>
|
||||
<div class='details'>
|
||||
<span>{{type.getName()}}</span>
|
||||
<span ng-show="model.composition !== undefined">
|
||||
{{model.composition.length}} Items
|
||||
- {{model.composition.length}} Item<span ng-show="model.composition.length > 1">s</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,7 +65,6 @@ define(
|
||||
// path to new, addressed, path based on
|
||||
// domainObject
|
||||
$location.path(urlService.urlForLocation("browse", domainObject));
|
||||
|
||||
}
|
||||
|
||||
// Callback for updating the in-scope reference to the object
|
||||
@ -128,6 +127,78 @@ define(
|
||||
navigateTo(domainObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Uses the current navigation to get the
|
||||
// current ContextCapability, then the
|
||||
// parent is gotten from that. If the parent
|
||||
// is not the root, then user is navigated to
|
||||
// parent
|
||||
function navigateToParent() {
|
||||
var context = navigationService.getNavigation().getCapability('context'),
|
||||
parentContext,
|
||||
parent,
|
||||
grandparentId;
|
||||
|
||||
// Checks if the current object has a context
|
||||
if (context) {
|
||||
|
||||
// Sets the parent and the parent context
|
||||
// which is checked
|
||||
parent = context.getParent();
|
||||
parentContext = parent.getCapability('context');
|
||||
|
||||
if ((parent.getId() !== ROOT_ID) && parentContext) {
|
||||
// Gets the grandparent id
|
||||
grandparentId = parentContext.getParent().getId();
|
||||
|
||||
// Navigates to the parent
|
||||
navigateTo(parent);
|
||||
|
||||
// Checks after navigation if the user is located at the
|
||||
// root (grandparent of original selected object, after
|
||||
// navigation, user is at parent of original object and
|
||||
// child of grandparent)
|
||||
if (grandparentId && grandparentId !== ROOT_ID) {
|
||||
$scope.atRoot = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set at root if no grandparent exists and
|
||||
// if grandparent is ROOT, after navigation
|
||||
$scope.atRoot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkRoot() {
|
||||
var context = navigationService.getNavigation().getCapability('context'),
|
||||
parentContext,
|
||||
parent,
|
||||
grandparent;
|
||||
|
||||
// Checks if the current object has a context
|
||||
if (context) {
|
||||
parent = context.getParent();
|
||||
parentContext = parent.getCapability('context');
|
||||
if ((parent.getId() !== ROOT_ID) && parentContext) {
|
||||
grandparent = parentContext.getParent();
|
||||
|
||||
// Checks if the grandparent exists
|
||||
// if it does not exist (for example in search),
|
||||
// than do not show the back button
|
||||
if (grandparent) {
|
||||
$scope.atRoot = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In any other situation where the context or parent
|
||||
// context does not exist or the user is at ROOT, than
|
||||
// hide the back arrow
|
||||
$scope.atRoot = true;
|
||||
|
||||
}
|
||||
|
||||
// Load the root object, put it in the scope.
|
||||
// Also, load its immediate children, and (possibly)
|
||||
@ -142,7 +213,13 @@ define(
|
||||
$scope.treeModel = {
|
||||
selectedObject: navigationService.getNavigation()
|
||||
};
|
||||
|
||||
|
||||
// SlideMenu boolean used to hide and show
|
||||
// tree menu
|
||||
$scope.treeSlide = function () {
|
||||
$scope.treeClass = !$scope.treeClass;
|
||||
};
|
||||
|
||||
// Listen for changes in navigation state.
|
||||
navigationService.addListener(setNavigation);
|
||||
|
||||
@ -153,6 +230,16 @@ define(
|
||||
$scope.$on("$destroy", function () {
|
||||
navigationService.removeListener(setNavigation);
|
||||
});
|
||||
|
||||
// If the user has selected an object (and is portrait
|
||||
// on a phone), then hide the tree menu
|
||||
$scope.$on("select-obj", function () {
|
||||
$scope.treeSlide();
|
||||
});
|
||||
|
||||
$scope.backArrow = navigateToParent;
|
||||
|
||||
$scope.checkRoot = checkRoot;
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,9 @@ define(
|
||||
mockUrlService,
|
||||
mockDomainObject,
|
||||
mockNextObject,
|
||||
mockParentContext,
|
||||
mockParent,
|
||||
mockGrandparent,
|
||||
controller;
|
||||
|
||||
function mockPromise(value) {
|
||||
@ -52,7 +55,7 @@ define(
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$on", "$watch" ]
|
||||
[ "$on", "$watch", "treeSlide", "backArrow" ]
|
||||
);
|
||||
mockRoute = { current: { params: {} } };
|
||||
mockLocation = jasmine.createSpyObj(
|
||||
@ -88,6 +91,17 @@ define(
|
||||
"nextObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
|
||||
|
||||
mockParentContext = jasmine.createSpyObj('context', ['getParent']);
|
||||
mockParent = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
mockGrandparent = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
|
||||
mockObjectService.getObjects.andReturn(mockPromise({
|
||||
ROOT: mockRootObject
|
||||
@ -145,13 +159,26 @@ define(
|
||||
);
|
||||
expect(mockScope.navigatedObject).toEqual(mockDomainObject);
|
||||
});
|
||||
|
||||
// Mocks the tree slide call that
|
||||
// lets the html code know if the
|
||||
// tree menu is open.
|
||||
it("calls the treeSlide function", function () {
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
"select-obj",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
mockScope.$on.calls[1].args[1]();
|
||||
});
|
||||
|
||||
it("releases its navigation listener when its scope is destroyed", function () {
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
"$destroy",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
|
||||
mockScope.$on.calls[0].args[1]();
|
||||
// Should remove the listener it added earlier
|
||||
expect(mockNavigationService.removeListener).toHaveBeenCalledWith(
|
||||
mockNavigationService.addListener.mostRecentCall.args[0]
|
||||
@ -237,7 +264,117 @@ define(
|
||||
mockUrlService.urlForLocation(mockMode, mockNextObject)
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it("checks if the user is current navigated to the root", function () {
|
||||
var mockContext = jasmine.createSpyObj('context', ['getParent']);
|
||||
|
||||
mockRoute.current.params.ids = "ROOT/mine";
|
||||
mockParent.getId.andReturn("ROOT");
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return c === 'context' && mockContext;
|
||||
});
|
||||
|
||||
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||
mockContext.getParent.andReturn(mockParent);
|
||||
mockParent.getCapability.andCallFake(function (c) {
|
||||
return c === 'context' && mockParentContext;
|
||||
});
|
||||
mockParentContext.getParent.andReturn(mockGrandparent);
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.checkRoot();
|
||||
|
||||
mockRoute.current.params.ids = "mine/junk";
|
||||
mockParent.getId.andReturn("mine");
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.checkRoot();
|
||||
|
||||
mockDomainObject.getCapability.andReturn(undefined);
|
||||
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.checkRoot();
|
||||
});
|
||||
|
||||
// Mocks the back arrow call that
|
||||
// lets the html code know the back
|
||||
// arrow navigation needs to be done
|
||||
it("calls the backArrow function", function () {
|
||||
var mockContext = jasmine.createSpyObj('context', ['getParent']);
|
||||
|
||||
mockRoute.current.params.ids = "mine/junk";
|
||||
mockParent.getId.andReturn("mine");
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return c === 'context' && mockContext;
|
||||
});
|
||||
|
||||
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||
mockContext.getParent.andReturn(mockParent);
|
||||
mockParent.getCapability.andCallFake(function (c) {
|
||||
return c === 'context' && mockParentContext;
|
||||
});
|
||||
mockParentContext.getParent.andReturn(mockGrandparent);
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.backArrow();
|
||||
|
||||
mockRoute.current.params.ids = "mine/lessjunk/morejunk";
|
||||
mockGrandparent.getId.andReturn("mine");
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.backArrow();
|
||||
|
||||
mockRoute.current.params.ids = "ROOT/mine";
|
||||
mockParent.getId.andReturn("ROOT");
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
|
||||
mockScope.backArrow();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -25,7 +25,7 @@
|
||||
All fields marked <span class="ui-symbol req">*</span> are required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs form outline editor">
|
||||
<div class="abs form editor">
|
||||
<div class='abs contents l-dialog'>
|
||||
<mct-form ng-model="ngModel.value"
|
||||
structure="ngModel.structure"
|
||||
|
@ -25,7 +25,7 @@
|
||||
<a href=""
|
||||
ng-click="ngModel.cancel()"
|
||||
ng-if="ngModel.cancel"
|
||||
class="btn normal ui-symbol close">
|
||||
class="clk-icon icon ui-symbol close">
|
||||
x
|
||||
</a>
|
||||
<div class="abs contents" ng-transclude>
|
||||
|
@ -93,7 +93,7 @@ define(
|
||||
var traverseObject = (navigationService).getNavigation();
|
||||
|
||||
// Stop when object is not defined (above ROOT)
|
||||
while (traverseObject) {
|
||||
while (traverseObject && traverseObject.getCapability('context')) {
|
||||
|
||||
// If object currently traversed to is object being removed
|
||||
// navigate to parent of current object and then exit loop
|
||||
|
@ -8,6 +8,10 @@
|
||||
"key": "urlService",
|
||||
"implementation": "/services/UrlService.js",
|
||||
"depends": [ "$location" ]
|
||||
},
|
||||
{
|
||||
"key": "agentService",
|
||||
"implementation": "/services/AgentService.js"
|
||||
}
|
||||
],
|
||||
"runs": [
|
||||
@ -60,7 +64,7 @@
|
||||
{
|
||||
"key": "TreeNodeController",
|
||||
"implementation": "controllers/TreeNodeController.js",
|
||||
"depends": [ "$scope", "$timeout" ]
|
||||
"depends": [ "$scope", "$timeout", "agentService" ]
|
||||
},
|
||||
{
|
||||
"key": "ActionGroupController",
|
||||
|
@ -48,6 +48,34 @@
|
||||
/************************** CONTROLS */
|
||||
/************************** PATHS */
|
||||
/************************** TIMINGS */
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/************************** STYLE */
|
||||
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
|
||||
/************************** MOBILE TREE MENU DIMENSIONS */
|
||||
/************************** WINDOW DIMENSIONS FOR RWD */
|
||||
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -121,83 +149,103 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/* line 22, ../sass/forms/_elems.scss */
|
||||
.section-header {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #cccccc;
|
||||
font-size: 0.8em;
|
||||
margin-top: 5px;
|
||||
padding: 5px; }
|
||||
/* line 28, ../sass/forms/_elems.scss */
|
||||
.section-header:first-child {
|
||||
margin-top: 0; }
|
||||
padding: 5px 5px;
|
||||
text-transform: uppercase; }
|
||||
|
||||
/* line 35, ../sass/forms/_elems.scss */
|
||||
.form .form-section {
|
||||
position: relative; }
|
||||
/* line 39, ../sass/forms/_elems.scss */
|
||||
position: relative;
|
||||
margin-bottom: 20px; }
|
||||
/* line 40, ../sass/forms/_elems.scss */
|
||||
.form .form-row {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
border-top: 1px solid #4d4d4d;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
margin-top: 5px;
|
||||
padding: 5px;
|
||||
padding: 5px 0;
|
||||
position: relative; }
|
||||
/* line 46, ../sass/forms/_elems.scss */
|
||||
/* line 48, ../sass/forms/_elems.scss */
|
||||
.form .form-row.first {
|
||||
border-top: none; }
|
||||
/* line 50, ../sass/forms/_elems.scss */
|
||||
.form .form-row .label,
|
||||
.form .form-row .controls {
|
||||
/* line 52, ../sass/forms/_elems.scss */
|
||||
.form .form-row > .label,
|
||||
.form .form-row > .controls {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
line-height: 22px;
|
||||
min-height: 22px; }
|
||||
/* line 61, ../sass/forms/_elems.scss */
|
||||
.form .form-row > .label {
|
||||
float: left;
|
||||
min-width: 120px;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
width: 20%; }
|
||||
/* line 69, ../sass/forms/_elems.scss */
|
||||
width: 30%; }
|
||||
/* line 71, ../sass/forms/_elems.scss */
|
||||
.form .form-row .value {
|
||||
color: #cccccc; }
|
||||
/* line 73, ../sass/forms/_elems.scss */
|
||||
/* line 75, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls {
|
||||
float: left;
|
||||
position: relative;
|
||||
width: 79.9%; }
|
||||
/* line 80, ../sass/forms/_elems.scss */
|
||||
width: 69.9%; }
|
||||
/* line 82, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls .l-composite-control.l-checkbox {
|
||||
display: inline-block;
|
||||
line-height: 14px;
|
||||
margin-right: 5px; }
|
||||
/* line 89, ../sass/forms/_elems.scss */
|
||||
/* line 91, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls .l-med input[type="text"] {
|
||||
width: 200px; }
|
||||
/* line 93, ../sass/forms/_elems.scss */
|
||||
/* line 95, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls .l-small input[type="text"] {
|
||||
width: 50px; }
|
||||
/* line 97, ../sass/forms/_elems.scss */
|
||||
/* line 99, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls .l-numeric input[type="text"] {
|
||||
text-align: right; }
|
||||
/* line 101, ../sass/forms/_elems.scss */
|
||||
/* line 103, ../sass/forms/_elems.scss */
|
||||
.form .form-row .controls .select {
|
||||
margin-right: 5px; }
|
||||
/* line 106, ../sass/forms/_elems.scss */
|
||||
/* line 108, ../sass/forms/_elems.scss */
|
||||
.form .form-row .field-hints {
|
||||
color: #666666; }
|
||||
/* line 110, ../sass/forms/_elems.scss */
|
||||
/* line 112, ../sass/forms/_elems.scss */
|
||||
.form .form-row .selector-list {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
@ -210,7 +258,7 @@
|
||||
position: relative;
|
||||
height: 150px;
|
||||
overflow: auto; }
|
||||
/* line 121, ../sass/forms/_elems.scss */
|
||||
/* line 123, ../sass/forms/_elems.scss */
|
||||
.form .form-row .selector-list .wrapper {
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
@ -219,24 +267,24 @@
|
||||
bottom: 5px;
|
||||
left: 5px; }
|
||||
|
||||
/* line 135, ../sass/forms/_elems.scss */
|
||||
/* line 137, ../sass/forms/_elems.scss */
|
||||
label.form-control.checkbox input {
|
||||
margin-right: 5px;
|
||||
vertical-align: top; }
|
||||
|
||||
/* line 141, ../sass/forms/_elems.scss */
|
||||
/* line 143, ../sass/forms/_elems.scss */
|
||||
.hint,
|
||||
.s-hint {
|
||||
font-size: 0.9em; }
|
||||
|
||||
/* line 146, ../sass/forms/_elems.scss */
|
||||
/* line 148, ../sass/forms/_elems.scss */
|
||||
.l-result {
|
||||
display: inline-block;
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
position: relative;
|
||||
vertical-align: top; }
|
||||
/* line 153, ../sass/forms/_elems.scss */
|
||||
/* line 155, ../sass/forms/_elems.scss */
|
||||
.l-result div.s-hint {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
@ -385,7 +433,7 @@ input[type="text"] {
|
||||
margin: 0 0 2px 2px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
/* line 162, ../sass/_mixins.scss */
|
||||
/* line 167, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
@ -394,10 +442,10 @@ input[type="text"] {
|
||||
background-image: -webkit-linear-gradient(#636363, #575757);
|
||||
background-image: linear-gradient(#636363, #575757);
|
||||
color: #bdbdbd; }
|
||||
/* line 165, ../sass/_mixins.scss */
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #878787; }
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
/* line 175, ../sass/_mixins.scss */
|
||||
.form-control.select.btn-menu .invoke-menu {
|
||||
color: #757575; }
|
||||
/* line 29, ../sass/forms/_selects.scss */
|
||||
|
@ -48,6 +48,34 @@
|
||||
/************************** CONTROLS */
|
||||
/************************** PATHS */
|
||||
/************************** TIMINGS */
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/************************** STYLE */
|
||||
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
|
||||
/************************** MOBILE TREE MENU DIMENSIONS */
|
||||
/************************** WINDOW DIMENSIONS FOR RWD */
|
||||
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -79,6 +107,27 @@
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -137,7 +186,7 @@
|
||||
margin-bottom: 3px;
|
||||
margin-right: 3px;
|
||||
position: relative; }
|
||||
/* line 162, ../sass/_mixins.scss */
|
||||
/* line 167, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzcwNzA3MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
@ -146,15 +195,15 @@
|
||||
background-image: -webkit-linear-gradient(#707070, #636363);
|
||||
background-image: linear-gradient(#707070, #636363);
|
||||
color: #bdbdbd; }
|
||||
/* line 165, ../sass/_mixins.scss */
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #949494; }
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
/* line 175, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.btn-menu .invoke-menu {
|
||||
color: #828282; }
|
||||
/* line 46, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-type {
|
||||
color: #0099cc !important; }
|
||||
color: deepskyblue !important; }
|
||||
/* line 48, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-type .l-icon-link {
|
||||
color: #49dedb; }
|
||||
@ -163,35 +212,35 @@
|
||||
opacity: 1; }
|
||||
/* line 57, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .contents {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px; }
|
||||
/* line 61, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
left: 10px; }
|
||||
/* line 63, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar {
|
||||
bottom: auto;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: right;
|
||||
z-index: 5; }
|
||||
/* line 66, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs .left, .items-holder .item.grid-item .bar.top-bar.abs .right {
|
||||
/* line 69, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar .left, .items-holder .item.grid-item .bar.top-bar .right {
|
||||
width: auto; }
|
||||
/* line 68, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs .left .icon, .items-holder .item.grid-item .bar.top-bar.abs .right .icon {
|
||||
/* line 71, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar .left .icon, .items-holder .item.grid-item .bar.top-bar .right .icon {
|
||||
margin-left: 3px; }
|
||||
/* line 70, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs .left .icon.l-icon-link, .items-holder .item.grid-item .bar.top-bar.abs .right .icon.l-icon-link {
|
||||
/* line 73, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar .left .icon.l-icon-link, .items-holder .item.grid-item .bar.top-bar .right .icon.l-icon-link {
|
||||
color: #49dedb; }
|
||||
/* line 76, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar.abs {
|
||||
/* line 79, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar {
|
||||
top: auto;
|
||||
height: 30px;
|
||||
padding: 5px; }
|
||||
/* line 82, ../sass/items/_item.scss */
|
||||
line-height: 110%; }
|
||||
/* line 85, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main {
|
||||
line-height: 160px;
|
||||
z-index: 1; }
|
||||
/* line 88, ../sass/items/_item.scss */
|
||||
/* line 91, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type {
|
||||
overflow: false;
|
||||
position: absolute;
|
||||
@ -201,24 +250,23 @@
|
||||
left: 40px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
color: #737373;
|
||||
text-align: center;
|
||||
font-size: 96.9px;
|
||||
line-height: 102px;
|
||||
bottom: auto;
|
||||
height: 102px;
|
||||
top: 30px; }
|
||||
/* line 100, ../sass/items/_item.scss */
|
||||
/* line 103, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type .l-icon-link {
|
||||
color: #1a8e8b;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
color: #49dedb;
|
||||
height: auto;
|
||||
line-height: 100%;
|
||||
position: absolute;
|
||||
font-size: 32px;
|
||||
font-size: 0.3em;
|
||||
left: 0px;
|
||||
bottom: 10px;
|
||||
z-index: 2; }
|
||||
/* line 112, ../sass/items/_item.scss */
|
||||
/* line 116, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-open {
|
||||
-moz-transition-property: "opacity";
|
||||
-o-transition-property: "opacity";
|
||||
@ -238,17 +286,20 @@
|
||||
width: 50px;
|
||||
pointer-events: none;
|
||||
text-align: right; }
|
||||
/* line 124, ../sass/items/_item.scss */
|
||||
/* line 128, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .title {
|
||||
text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px;
|
||||
color: #cccccc;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis; }
|
||||
/* line 132, ../sass/items/_item.scss */
|
||||
color: #cccccc; }
|
||||
/* line 133, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .details {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.8em; }
|
||||
/* line 135, ../sass/items/_item.scss */
|
||||
/* line 137, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzBhYzJmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYjRmMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
@ -270,7 +321,7 @@
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
color: #80dfff; }
|
||||
/* line 162, ../sass/_mixins.scss */
|
||||
/* line 167, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzJlY2JmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzE0YzRmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
@ -279,21 +330,123 @@
|
||||
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
|
||||
background-image: linear-gradient(#2ecbff, #14c4ff);
|
||||
color: #bdbdbd; }
|
||||
/* line 165, ../sass/_mixins.scss */
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #75ddff; }
|
||||
/* line 170, ../sass/_mixins.scss */
|
||||
/* line 175, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected.btn-menu .invoke-menu {
|
||||
color: #52d4ff; }
|
||||
/* line 140, ../sass/items/_item.scss */
|
||||
/* line 142, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-type, .items-holder .item.grid-item.selected .top-bar .icon:not(.alert) {
|
||||
color: #80dfff; }
|
||||
/* line 141, ../sass/items/_item.scss */
|
||||
/* line 143, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-main .item-open {
|
||||
color: #80dfff; }
|
||||
/* line 142, ../sass/items/_item.scss */
|
||||
/* line 144, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .title {
|
||||
color: white; }
|
||||
/* line 144, ../sass/items/_item.scss */
|
||||
/* line 146, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected:hover .item-main .item-type {
|
||||
color: white !important; }
|
||||
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 1024px) and (max-device-height: 799px), screen and (orientation: portrait) and (min-width: 515px) and (max-width: 799px) and (min-height: 741px) and (max-height: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 1024px) and (max-device-height: 799px) {
|
||||
/* line 29, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
width: 100%; }
|
||||
/* line 33, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item > .contents {
|
||||
top: 0px;
|
||||
right: 10px;
|
||||
bottom: 0px;
|
||||
left: 10px; }
|
||||
/* line 37, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar {
|
||||
bottom: 0 !important;
|
||||
left: auto !important;
|
||||
right: 20px !important;
|
||||
width: 40px !important;
|
||||
height: auto !important;
|
||||
text-align: right; }
|
||||
/* line 44, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar {
|
||||
left: 40px;
|
||||
right: 60px; }
|
||||
/* line 52, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type {
|
||||
font-size: 30px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
line-height: 100%;
|
||||
text-align: left;
|
||||
width: 30px; }
|
||||
/* line 61, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type .l-icon-link {
|
||||
bottom: 0; }
|
||||
/* line 65, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-open {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
font-size: 1em;
|
||||
width: auto; } }
|
||||
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 1024px) and (max-device-height: 799px) {
|
||||
/* line 29, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
height: 50px; }
|
||||
/* line 78, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar {
|
||||
line-height: 50px !important; }
|
||||
/* line 82, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar {
|
||||
top: 7px;
|
||||
bottom: auto;
|
||||
height: 35px; }
|
||||
/* line 87, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type {
|
||||
top: 10px;
|
||||
bottom: auto;
|
||||
height: 30px; }
|
||||
/* line 90, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-open {
|
||||
line-height: 50px; } }
|
||||
@media screen and (orientation: portrait) and (min-width: 515px) and (max-width: 799px) and (min-height: 741px) and (max-height: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 1024px) and (max-device-height: 799px) {
|
||||
/* line 29, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
height: 66px; }
|
||||
/* line 100, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar {
|
||||
line-height: 66px !important; }
|
||||
/* line 104, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar {
|
||||
top: 15px;
|
||||
bottom: auto;
|
||||
height: 35px; }
|
||||
/* line 109, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type {
|
||||
top: 18px;
|
||||
bottom: auto;
|
||||
height: 30px; }
|
||||
/* line 112, ../sass/mobile/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-open {
|
||||
line-height: 66px; } }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,34 @@
|
||||
/************************** CONTROLS */
|
||||
/************************** PATHS */
|
||||
/************************** TIMINGS */
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/************************** STYLE */
|
||||
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
|
||||
/************************** MOBILE TREE MENU DIMENSIONS */
|
||||
/************************** WINDOW DIMENSIONS FOR RWD */
|
||||
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -79,6 +107,27 @@
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -104,7 +153,7 @@
|
||||
ul.tree {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
/* line 308, ../sass/_mixins.scss */
|
||||
/* line 314, ../sass/_mixins.scss */
|
||||
ul.tree li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
@ -113,144 +162,175 @@ ul.tree {
|
||||
ul.tree li {
|
||||
display: block;
|
||||
position: relative; }
|
||||
/* line 28, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-transition: background-color 0.25s;
|
||||
-o-transition: background-color 0.25s;
|
||||
-webkit-transition: background-color 0.25s;
|
||||
transition: background-color 0.25s;
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
margin-bottom: 3px;
|
||||
position: relative; }
|
||||
/* line 39, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .view-control {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
font-size: 0.75em;
|
||||
width: 10px; }
|
||||
/* line 45, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .view-control:hover {
|
||||
color: #ffc700; }
|
||||
/* line 50, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
left: 15px; }
|
||||
/* line 57, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label .type-icon {
|
||||
overflow: false;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
text-shadow: rgba(0, 0, 0, 0.6) 0 1px 2px;
|
||||
color: #0099cc;
|
||||
left: 5px;
|
||||
right: auto;
|
||||
width: 1em; }
|
||||
/* line 65, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label .type-icon .icon.l-icon-link, ul.tree li span.tree-item .label .type-icon .icon.l-icon-alert {
|
||||
text-shadow: black 0 1px 2px;
|
||||
position: absolute;
|
||||
z-index: 2; }
|
||||
/* line 71, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label .type-icon .icon.l-icon-alert {
|
||||
color: #ff3c00;
|
||||
font-size: 8px;
|
||||
line-height: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
top: 1px;
|
||||
right: -2px; }
|
||||
/* line 77, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label .type-icon .icon.l-icon-link {
|
||||
color: #49dedb;
|
||||
font-size: 8px;
|
||||
line-height: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
left: -3px;
|
||||
bottom: 5px; }
|
||||
/* line 86, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .label .title-label {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: block;
|
||||
left: 30px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
/* line 97, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.loading {
|
||||
pointer-events: none; }
|
||||
/* line 99, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.loading .label {
|
||||
opacity: 0.5; }
|
||||
/* line 101, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.loading .label .title-label {
|
||||
font-style: italic; }
|
||||
/* line 105, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.loading .wait-spinner {
|
||||
margin-left: 14px; }
|
||||
/* line 110, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.selected {
|
||||
background: #005177;
|
||||
color: #fff; }
|
||||
/* line 114, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.selected .view-control {
|
||||
color: #0099cc; }
|
||||
/* line 117, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item.selected .label .type-icon {
|
||||
color: #fff; }
|
||||
/* line 123, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.selected):hover {
|
||||
background: #404040;
|
||||
color: #cccccc; }
|
||||
/* line 126, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.selected):hover .context-trigger {
|
||||
display: block; }
|
||||
/* line 129, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.selected):hover .icon {
|
||||
color: #33ccff; }
|
||||
/* line 135, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.loading) {
|
||||
cursor: pointer; }
|
||||
/* line 139, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger {
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: 3px; }
|
||||
/* line 145, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger .invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: 0.9rem;
|
||||
line-height: 0.9rem; }
|
||||
/* line 154, ../sass/tree/_tree.scss */
|
||||
/* line 29, ../sass/tree/_tree.scss */
|
||||
ul.tree ul.tree {
|
||||
margin-left: 15px; }
|
||||
|
||||
/* line 34, ../sass/tree/_tree.scss */
|
||||
.tree-item,
|
||||
.search-result-item {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-transition: background-color 0.25s;
|
||||
-o-transition: background-color 0.25s;
|
||||
-webkit-transition: background-color 0.25s;
|
||||
transition: background-color 0.25s;
|
||||
display: block;
|
||||
font-size: 0.8rem;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
margin-bottom: 3px;
|
||||
position: relative; }
|
||||
/* line 47, ../sass/tree/_tree.scss */
|
||||
.tree-item .view-control,
|
||||
.search-result-item .view-control {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
font-size: 0.75em;
|
||||
width: 10px; }
|
||||
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
|
||||
/* line 55, ../sass/tree/_tree.scss */
|
||||
.tree-item .view-control:hover,
|
||||
.search-result-item .view-control:hover {
|
||||
color: #ffc700; } }
|
||||
/* line 61, ../sass/tree/_tree.scss */
|
||||
.tree-item .label,
|
||||
.search-result-item .label {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
line-height: 1.5rem; }
|
||||
/* line 69, ../sass/tree/_tree.scss */
|
||||
.tree-item .label .type-icon,
|
||||
.search-result-item .label .type-icon {
|
||||
text-shadow: rgba(0, 0, 0, 0.6) 0 1px 2px;
|
||||
font-size: 16px;
|
||||
color: #0099cc;
|
||||
left: 5px;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
bottom: auto;
|
||||
height: 16px;
|
||||
line-height: 100%;
|
||||
right: auto;
|
||||
width: 16px; }
|
||||
/* line 82, ../sass/tree/_tree.scss */
|
||||
.tree-item .label .type-icon .icon.l-icon-link, .tree-item .label .type-icon .icon.l-icon-alert,
|
||||
.search-result-item .label .type-icon .icon.l-icon-link,
|
||||
.search-result-item .label .type-icon .icon.l-icon-alert {
|
||||
text-shadow: black 0 1px 2px;
|
||||
position: absolute;
|
||||
z-index: 2; }
|
||||
/* line 88, ../sass/tree/_tree.scss */
|
||||
.tree-item .label .type-icon .icon.l-icon-alert,
|
||||
.search-result-item .label .type-icon .icon.l-icon-alert {
|
||||
color: #ff3c00;
|
||||
font-size: 8px;
|
||||
line-height: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
top: 1px;
|
||||
right: -2px; }
|
||||
/* line 94, ../sass/tree/_tree.scss */
|
||||
.tree-item .label .type-icon .icon.l-icon-link,
|
||||
.search-result-item .label .type-icon .icon.l-icon-link {
|
||||
color: #49dedb;
|
||||
font-size: 8px;
|
||||
line-height: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
left: -3px;
|
||||
bottom: 0px; }
|
||||
/* line 102, ../sass/tree/_tree.scss */
|
||||
.tree-item .label .title-label,
|
||||
.search-result-item .label .title-label {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: block;
|
||||
left: 30px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
/* line 113, ../sass/tree/_tree.scss */
|
||||
.tree-item.loading,
|
||||
.search-result-item.loading {
|
||||
pointer-events: none; }
|
||||
/* line 115, ../sass/tree/_tree.scss */
|
||||
.tree-item.loading .label,
|
||||
.search-result-item.loading .label {
|
||||
opacity: 0.5; }
|
||||
/* line 117, ../sass/tree/_tree.scss */
|
||||
.tree-item.loading .label .title-label,
|
||||
.search-result-item.loading .label .title-label {
|
||||
font-style: italic; }
|
||||
/* line 121, ../sass/tree/_tree.scss */
|
||||
.tree-item.loading .wait-spinner,
|
||||
.search-result-item.loading .wait-spinner {
|
||||
margin-left: 14px; }
|
||||
/* line 126, ../sass/tree/_tree.scss */
|
||||
.tree-item.selected,
|
||||
.search-result-item.selected {
|
||||
background: #005177;
|
||||
color: #fff; }
|
||||
/* line 130, ../sass/tree/_tree.scss */
|
||||
.tree-item.selected .view-control,
|
||||
.search-result-item.selected .view-control {
|
||||
color: #0099cc; }
|
||||
/* line 133, ../sass/tree/_tree.scss */
|
||||
.tree-item.selected .label .type-icon,
|
||||
.search-result-item.selected .label .type-icon {
|
||||
color: #fff; }
|
||||
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
|
||||
/* line 141, ../sass/tree/_tree.scss */
|
||||
.tree-item:not(.selected):hover,
|
||||
.search-result-item:not(.selected):hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #cccccc; }
|
||||
/* line 144, ../sass/tree/_tree.scss */
|
||||
.tree-item:not(.selected):hover .context-trigger,
|
||||
.search-result-item:not(.selected):hover .context-trigger {
|
||||
display: block; }
|
||||
/* line 147, ../sass/tree/_tree.scss */
|
||||
.tree-item:not(.selected):hover .icon,
|
||||
.search-result-item:not(.selected):hover .icon {
|
||||
color: #33ccff; } }
|
||||
/* line 154, ../sass/tree/_tree.scss */
|
||||
.tree-item:not(.loading),
|
||||
.search-result-item:not(.loading) {
|
||||
cursor: pointer; }
|
||||
/* line 158, ../sass/tree/_tree.scss */
|
||||
.tree-item .context-trigger,
|
||||
.search-result-item .context-trigger {
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: 3px; }
|
||||
/* line 164, ../sass/tree/_tree.scss */
|
||||
.tree-item .context-trigger .invoke-menu,
|
||||
.search-result-item .context-trigger .invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: 0.9rem;
|
||||
line-height: 0.9rem; }
|
||||
|
||||
/* line 173, ../sass/tree/_tree.scss */
|
||||
.tree-item .label {
|
||||
left: 15px; }
|
||||
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -272,227 +352,34 @@ ul.tree {
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* line 23, ../sass/search/_search.scss */
|
||||
.abs.search-holder {
|
||||
height: 25px;
|
||||
bottom: 0;
|
||||
z-index: 5; }
|
||||
/* line 27, ../sass/search/_search.scss */
|
||||
.abs.search-holder.active {
|
||||
height: auto;
|
||||
bottom: 0; }
|
||||
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 1024px) and (max-device-height: 799px), screen and (orientation: portrait) and (min-width: 515px) and (max-width: 799px) and (min-height: 741px) and (max-height: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 1024px) and (max-device-height: 799px) {
|
||||
/* line 27, ../sass/mobile/_tree.scss */
|
||||
ul.tree ul.tree {
|
||||
margin-left: 20px; }
|
||||
|
||||
/* line 38, ../sass/search/_search.scss */
|
||||
.search {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%; }
|
||||
/* line 49, ../sass/search/_search.scss */
|
||||
.search .search-bar {
|
||||
font-size: 0.8em;
|
||||
position: relative;
|
||||
width: 100%; }
|
||||
/* line 66, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-input {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0; }
|
||||
/* line 73, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-icon,
|
||||
.search .search-bar .clear-icon,
|
||||
.search .search-bar .menu-icon {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
color: #737373;
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
line-height: 17px;
|
||||
/* line 31, ../sass/mobile/_tree.scss */
|
||||
.tree-item,
|
||||
.search-result-item {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
margin-bottom: 0px; }
|
||||
/* line 36, ../sass/mobile/_tree.scss */
|
||||
.tree-item .view-control,
|
||||
.search-result-item .view-control {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 4px; }
|
||||
/* line 86, ../sass/search/_search.scss */
|
||||
.search .search-bar .clear-icon,
|
||||
.search .search-bar .menu-icon {
|
||||
cursor: pointer;
|
||||
transition: color .25s; }
|
||||
/* line 93, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-input {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-left: 22px !important;
|
||||
padding-right: 44px !important; }
|
||||
/* line 100, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-input input {
|
||||
width: 100%; }
|
||||
/* line 105, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-icon {
|
||||
color: #737373;
|
||||
left: 3px;
|
||||
transition: visibility .15s, opacity .15s, color .2s;
|
||||
pointer-events: none; }
|
||||
/* line 125, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-input:hover + div.search-icon {
|
||||
color: #a6a6a6; }
|
||||
/* line 129, ../sass/search/_search.scss */
|
||||
.search .search-bar .clear-icon {
|
||||
right: 22px;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility .15s, opacity .15s, color .2s; }
|
||||
/* line 138, ../sass/search/_search.scss */
|
||||
.search .search-bar .clear-icon.content {
|
||||
visibility: visible;
|
||||
opacity: 1; }
|
||||
/* line 143, ../sass/search/_search.scss */
|
||||
.search .search-bar .clear-icon:hover {
|
||||
color: #a6a6a6; }
|
||||
/* line 148, ../sass/search/_search.scss */
|
||||
.search .search-bar .menu-icon {
|
||||
font-size: 0.8em;
|
||||
padding-right: 4px;
|
||||
right: 4px;
|
||||
text-align: right; }
|
||||
/* line 154, ../sass/search/_search.scss */
|
||||
.search .search-bar .menu-icon:hover {
|
||||
color: #a6a6a6; }
|
||||
/* line 159, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-menu-holder {
|
||||
float: right;
|
||||
left: -20px;
|
||||
z-index: 1;
|
||||
transition: visibility .05s, opacity .05s; }
|
||||
/* line 169, ../sass/search/_search.scss */
|
||||
.search .search-bar .search-menu-holder.off {
|
||||
visibility: hidden;
|
||||
opacity: 0; }
|
||||
/* line 176, ../sass/search/_search.scss */
|
||||
.search .search-bar .menu-icon:hover + div.search-menu-holder {
|
||||
visibility: visible; }
|
||||
/* line 179, ../sass/search/_search.scss */
|
||||
.search .search-bar div.search-menu-holder:hover {
|
||||
visibility: visible; }
|
||||
/* line 184, ../sass/search/_search.scss */
|
||||
.search .active-filter-display {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
line-height: 130%;
|
||||
padding: 5px 0;
|
||||
padding-left: 1.4625em;
|
||||
font-size: 0.65em;
|
||||
margin-top: 3px; }
|
||||
/* line 199, ../sass/search/_search.scss */
|
||||
.search .active-filter-display .clear-filters-icon {
|
||||
opacity: 0.4;
|
||||
font-size: 0.8em;
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
cursor: pointer; }
|
||||
/* line 210, ../sass/search/_search.scss */
|
||||
.search .active-filter-display.off {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0; }
|
||||
/* line 220, ../sass/search/_search.scss */
|
||||
.search .search-scroll {
|
||||
order: 3;
|
||||
margin-top: 4px;
|
||||
overflow-y: auto;
|
||||
top: auto;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
position: relative; }
|
||||
/* line 235, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item {
|
||||
-moz-transition: background-color 0.25s;
|
||||
-o-transition: background-color 0.25s;
|
||||
-webkit-transition: background-color 0.25s;
|
||||
transition: background-color 0.25s;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 2px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 2px; }
|
||||
/* line 249, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item .label {
|
||||
margin-left: 6px; }
|
||||
/* line 253, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item .label .title-label {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 29px;
|
||||
right: 5px;
|
||||
font-size: .8em;
|
||||
line-height: 17px;
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
/* line 275, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item.selected {
|
||||
background: #005177;
|
||||
color: #fff; }
|
||||
/* line 279, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item.selected .view-control {
|
||||
color: #0099cc; }
|
||||
/* line 282, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item.selected .label .type-icon {
|
||||
color: #fff; }
|
||||
/* line 287, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item .label .type-icon .l-icon-link {
|
||||
display: none;
|
||||
text-shadow: black 0 1px 2px;
|
||||
z-index: 2;
|
||||
color: #49dedb;
|
||||
font-size: 8px;
|
||||
line-height: 8px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
margin-left: -25px; }
|
||||
/* line 299, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item:not(.selected):hover {
|
||||
background: #404040;
|
||||
color: #cccccc; }
|
||||
/* line 302, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item:not(.selected):hover .context-trigger {
|
||||
display: block; }
|
||||
/* line 305, ../sass/search/_search.scss */
|
||||
.search .search-scroll .results .search-result-item:not(.selected):hover .icon {
|
||||
color: #33ccff; }
|
||||
/* line 313, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-icon {
|
||||
position: relative; }
|
||||
/* line 315, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-icon.loading {
|
||||
pointer-events: none;
|
||||
margin-left: 6px; }
|
||||
/* line 319, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-icon.loading .title-label {
|
||||
font-style: italic;
|
||||
font-size: .9em;
|
||||
opacity: 0.5;
|
||||
margin-left: 26px;
|
||||
line-height: 24px; }
|
||||
/* line 329, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-icon.loading .wait-spinner {
|
||||
margin-left: 6px; }
|
||||
/* line 334, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-icon:not(.loading) {
|
||||
cursor: pointer; }
|
||||
/* line 339, ../sass/search/_search.scss */
|
||||
.search .search-scroll .load-more-button {
|
||||
margin-top: 5px 0;
|
||||
font-size: 0.8em;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
margin-left: -45px;
|
||||
text-align: center;
|
||||
width: 90px;
|
||||
white-space: nowrap; }
|
||||
font-size: 1.1em;
|
||||
right: 0px;
|
||||
width: 30px;
|
||||
text-align: center; }
|
||||
/* line 45, ../sass/mobile/_tree.scss */
|
||||
.tree-item .label,
|
||||
.search-result-item .label {
|
||||
left: 0;
|
||||
right: 35px;
|
||||
line-height: 35px; }
|
||||
/* line 50, ../sass/mobile/_tree.scss */
|
||||
.tree-item .label .type-icon,
|
||||
.search-result-item .label .type-icon {
|
||||
top: 9px;
|
||||
bottom: auto;
|
||||
height: 16px; } }
|
||||
|
Binary file not shown.
@ -83,7 +83,8 @@
|
||||
<glyph unicode="" glyph-name="icon-tabular" d="M0 896v-192h448v256h-384c-35.2 0-64-28.8-64-64zM960 960h-384v-256h448v192c0 35.2-28.8 64-64 64zM576 576h448v-256h-448v256zM0 576h448v-256h-448v256zM0 0c0-35.2 28.8-64 64-64h384v256h-448v-192zM576-64h384c35.2 0 64 28.8 64 64v192h-448v-256z" />
|
||||
<glyph unicode="" glyph-name="icon-calendar" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM640 512h-256v192h256v-192zM384 448h256v-192h-256v192zM320 256h-256v192h256v-192zM320 704v-192h-256v192h256zM128 0c-17 0-33 6.6-45.2 18.8s-18.8 28.2-18.8 45.2v128h256v-192h-192zM384 0v192h256v-192h-256zM960 64c0-17-6.6-33-18.8-45.2s-28.2-18.8-45.2-18.8h-192v192h256v-128zM960 256h-256v192h256v-192zM960 512h-256v192h256v-192z" />
|
||||
<glyph unicode="" glyph-name="icon-paint-bucket" d="M896 320c0 0-130-188-128-256 2-70.6 57.4-128 128-128s126 57.4 128 128c2 68-128 256-128 256zM449 831l0.2 64.8c0 35.4-28.4 64-63.8 64.2 0 0-0.2 0-0.2 0-35.2 0-63.8-28.6-64-63.8l-0.6-190.8-294-292.6c-50-50-12.4-215.2 112.4-340s290-162.4 340-112.4l417 423.6-447 447zM384 320c-70.6 0-128 57.4-128 128 0 47.4 25.8 89 64.4 111l-0.4-110.8c0-35.4 28.4-64 63.8-64.2 0 0 0.2 0 0.2 0 35.2 0 63.8 28.6 64 63.8l0.4 110.8c38-22.2 63.6-63.4 63.6-110.6 0-70.6-57.4-128-128-128z" />
|
||||
<glyph unicode="" glyph-name="icon-x-in-circle" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM832 256l-128-128-192 192-192-192-128 128 192 192-192 192 128 128 192-192 192 192 128-128-192-192 192-192z" />
|
||||
<glyph unicode="" glyph-name="icon-x-in-circle-heavy" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM832 256l-128-128-192 192-192-192-128 128 192 192-192 192 128 128 192-192 192 192 128-128-192-192 192-192z" />
|
||||
<glyph unicode="" glyph-name="icon-info" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM512 832c70.6 0 128-57.4 128-128s-57.4-128-128-128c-70.6 0-128 57.4-128 128s57.4 128 128 128zM704 128h-384v128h128v128h-128v128h320v-256h64v-128z" />
|
||||
<glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 448l-448-512v1024zM448 960l-448-512 448-512z" />
|
||||
<glyph unicode="" glyph-name="icon-x" d="M384 448l-365.332-365.332c-24.89-24.89-24.89-65.62 0-90.51l37.49-37.49c24.89-24.89 65.62-24.89 90.51 0 0 0 365.332 365.332 365.332 365.332l365.332-365.332c24.89-24.89 65.62-24.89 90.51 0l37.49 37.49c24.89 24.89 24.89 65.62 0 90.51l-365.332 365.332c0 0 365.332 365.332 365.332 365.332 24.89 24.89 24.89 65.62 0 90.51l-37.49 37.49c-24.89 24.89-65.62 24.89-90.51 0 0 0-365.332-365.332-365.332-365.332l-365.332 365.332c-24.89 24.89-65.62 24.89-90.51 0l-37.49-37.49c-24.89-24.89-24.89-65.62 0-90.51 0 0 365.332-365.332 365.332-365.332z" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
Binary file not shown.
Binary file not shown.
@ -47,6 +47,8 @@ $colorPausedBg: #c56f01;
|
||||
$colorPausedFg: #fff;
|
||||
$colorCreateBtn: $colorKey;
|
||||
$colorGridLines: rgba(#fff, 0.05);
|
||||
$colorFormLines: rgba(#fff, 0.1);
|
||||
$colorFormSectionHeader: rgba(#000, 0.2);
|
||||
// Menu colors
|
||||
$colorMenuBg: lighten($colorBodyBg, 23%);
|
||||
$colorMenuFg: lighten($colorMenuBg, 70%);
|
||||
@ -104,6 +106,7 @@ $treeSearchInputBarH: 25px;
|
||||
// Overlay
|
||||
$ovrTopBarH: 60px;
|
||||
$ovrFooterH: 40px;
|
||||
$overlayMargin: 25px;
|
||||
// Items
|
||||
$ueBrowseGridItemLg: 200px;
|
||||
$ueBrowseGridItemTopBarH: 20px;
|
||||
@ -111,6 +114,7 @@ $ueBrowseGridItemBottomBarH: 30px;
|
||||
$itemPadLR: 5px;
|
||||
// Tree
|
||||
$treeVCW: 10px;
|
||||
$treeTypeIconH: 16px;
|
||||
$treeTypeIconW: 20px;
|
||||
$treeContextTriggerW: 20px;
|
||||
$colorItemTreeIcon: $colorKey;
|
||||
@ -144,10 +148,13 @@ $reqSymbolFontSize: 0.7em;
|
||||
|
||||
/************************** CONTROLS */
|
||||
$controlDisabledOpacity: 0.3;
|
||||
$formLabelW: 20%;
|
||||
$formLabelW: 30%;
|
||||
$formInputH: 22px;
|
||||
$formRowCtrlsH: 14px;
|
||||
$formTBPad: $interiorMargin;
|
||||
$formLRPad: $interiorMargin;
|
||||
$menuLineH: 1.5rem;
|
||||
$menuLineHPx: 24px;
|
||||
$scrollbarTrackSize: 10px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
||||
$btnStdH: 25px;
|
||||
|
@ -71,12 +71,6 @@ p {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
}
|
||||
|
||||
span {
|
||||
/* 618 DEBUG
|
||||
box-sizing: border-box;
|
||||
*/
|
||||
}
|
||||
|
||||
mct-container {
|
||||
display: block;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bar .icon {
|
||||
.bar .ui-symbol {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@ -65,9 +65,9 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.tree-item .type-icon {
|
||||
font-size: 16px; // 16px is crisp size
|
||||
}
|
||||
//.tree-item .type-icon {
|
||||
// font-size: 16px; // 16px is crisp size
|
||||
//}
|
||||
|
||||
.l-icon-link:before {
|
||||
content: "\f4";
|
||||
|
@ -1,4 +1,3 @@
|
||||
/*****************************************************************************
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -28,11 +27,13 @@
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "mixins";
|
||||
@import "mobile/mixins";
|
||||
|
||||
@import "effects";
|
||||
@import "global";
|
||||
@import "fonts";
|
||||
@import "user-environ/layout";
|
||||
//@import "search/layout";
|
||||
@import "mobile/layout";
|
||||
@import "fixed-position";
|
||||
@import "about";
|
||||
@import "text";
|
||||
@ -46,6 +47,7 @@
|
||||
@import "controls/controls";
|
||||
@import "controls/lists";
|
||||
@import "controls/menus";
|
||||
@import "mobile/controls/menus";
|
||||
@import "controls/time-controller";
|
||||
@import "edit/editor";
|
||||
@import "features/imagery";
|
||||
@ -58,11 +60,14 @@
|
||||
@import "forms/datetime";
|
||||
@import "forms/filter";
|
||||
@import "plots/plots-main";
|
||||
@import "search/search";
|
||||
@import "mobile/search/search";
|
||||
@import "overlay/overlay";
|
||||
@import "mobile/overlay/overlay";
|
||||
@import "user-environ/frame";
|
||||
@import "user-environ/top-bar";
|
||||
@import "user-environ/bottom-bar";
|
||||
@import "user-environ/object-browse";
|
||||
//@import "user-environ/object-browse";
|
||||
@import "user-environ/tool-bar";
|
||||
@import "helpers/bubbles";
|
||||
@import "helpers/splitter";
|
||||
|
@ -19,157 +19,162 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
@mixin absPosDefault($offset: 0px, $overflowHidden: hidden) {
|
||||
overflow: $overflowHidden;
|
||||
position: absolute;
|
||||
top: $offset; right: $offset; bottom: $offset; left: $offset;
|
||||
width: auto; height: auto;
|
||||
top: $offset;
|
||||
right: $offset;
|
||||
bottom: $offset;
|
||||
left: $offset;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@mixin ancillaryIcon($d, $c) {
|
||||
// Used for small icons used in combination with larger icons,
|
||||
// like the link and alert icons in tree items.
|
||||
color: $c;
|
||||
font-size: $d;
|
||||
line-height: $d;
|
||||
height: $d;
|
||||
width: $d;
|
||||
// Used for small icons used in combination with larger icons,
|
||||
// like the link and alert icons in tree items.
|
||||
color: $c;
|
||||
font-size: $d;
|
||||
line-height: $d;
|
||||
height: $d;
|
||||
width: $d;
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice($props, $t: 500ms) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property($props);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property($props);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-fade($t: 0.5s) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property(visibility, opacity, background-color, border-color);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property(visibility, opacity, background-color, border-color);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-h($t: 0.5s) {
|
||||
@include transition-property(height, bottom, top);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-property(height, bottom, top);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-w($t: 0.5s) {
|
||||
@include transition-property(width, left, right);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-property(width, left, right);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin triangle-right($size, $color) {
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: $size/$ratio solid transparent;
|
||||
border-left: $size solid $color;
|
||||
border-bottom: $size/$ratio solid transparent;
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: $size/$ratio solid transparent;
|
||||
border-left: $size solid $color;
|
||||
border-bottom: $size/$ratio solid transparent;
|
||||
}
|
||||
|
||||
@mixin triangle-down($size, $color) {
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: $size/$ratio solid transparent;
|
||||
border-top: $size solid $color;
|
||||
border-right: $size/$ratio solid transparent;
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: $size/$ratio solid transparent;
|
||||
border-top: $size solid $color;
|
||||
border-right: $size/$ratio solid transparent;
|
||||
}
|
||||
|
||||
@mixin triangle($dir: "left", $size: 5px, $ratio: 1, $color: red) {
|
||||
//$size: $size*2;
|
||||
width: 0;
|
||||
height: 0;
|
||||
$slopedB: $size/$ratio solid transparent;
|
||||
$straightB: $size solid $color;
|
||||
@if $dir == "up" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-bottom: $straightB;
|
||||
} @else if $dir == "right" {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-left: $straightB;
|
||||
} @else if $dir == "down" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-top: $straightB;
|
||||
} @else {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-right: $straightB;
|
||||
}
|
||||
//$size: $size*2;
|
||||
width: 0;
|
||||
height: 0;
|
||||
$slopedB: $size/$ratio solid transparent;
|
||||
$straightB: $size solid $color;
|
||||
@if $dir == "up" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-bottom: $straightB;
|
||||
} @else if $dir == "right" {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-left: $straightB;
|
||||
} @else if $dir == "down" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-top: $straightB;
|
||||
} @else {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-right: $straightB;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
|
||||
@include background-image(linear-gradient(-45deg,
|
||||
rgba($c, $a) 25%, transparent 25%,
|
||||
transparent 50%, rgba($c, $a) 50%,
|
||||
rgba($c, $a) 75%, transparent 75%,
|
||||
transparent 100%
|
||||
));
|
||||
background-repeat: repeat;
|
||||
background-size: $d $d;
|
||||
@include background-image(linear-gradient(-45deg,
|
||||
rgba($c, $a) 25%, transparent 25%,
|
||||
transparent 50%, rgba($c, $a) 50%,
|
||||
rgba($c, $a) 75%, transparent 75%,
|
||||
transparent 100%
|
||||
));
|
||||
background-repeat: repeat;
|
||||
background-size: $d $d;
|
||||
}
|
||||
|
||||
@mixin bgTicks($c: $colorBodyFg, $repeatDir: 'x') {
|
||||
$deg: 90deg;
|
||||
@if ($repeatDir != 'x') {
|
||||
$deg: 0deg;
|
||||
$repeatDir: repeat-y;
|
||||
} @else {
|
||||
$repeatDir: repeat-x;
|
||||
}
|
||||
$deg: 90deg;
|
||||
@if ($repeatDir != 'x') {
|
||||
$deg: 0deg;
|
||||
$repeatDir: repeat-y;
|
||||
} @else {
|
||||
$repeatDir: repeat-x;
|
||||
}
|
||||
|
||||
@include background-image(linear-gradient($deg,
|
||||
$c 1px, transparent 1px,
|
||||
transparent 100%
|
||||
));
|
||||
background-repeat: $repeatDir;
|
||||
@include background-image(linear-gradient($deg,
|
||||
$c 1px, transparent 1px,
|
||||
transparent 100%
|
||||
));
|
||||
background-repeat: $repeatDir;
|
||||
}
|
||||
|
||||
@mixin containerSubtle($bg: $colorBodyBg, $fg: $colorBodyFg, $hover: false) {
|
||||
$ltnRatio: 7%;
|
||||
$gradRatio: 5%;
|
||||
$hovRatio: 7%;
|
||||
$bgBase: lighten($bg, $ltnRatio);
|
||||
$fgBase: lighten($fg, $ltnRatio);
|
||||
$gradC1: lighten($bgBase, $gradRatio);
|
||||
$gradC2: $bgBase;
|
||||
$cInvokeBase: lighten($gradC1, $ltnRatio*2);
|
||||
$ltnRatio: 7%;
|
||||
$gradRatio: 5%;
|
||||
$hovRatio: 7%;
|
||||
$bgBase: lighten($bg, $ltnRatio);
|
||||
$fgBase: lighten($fg, $ltnRatio);
|
||||
$gradC1: lighten($bgBase, $gradRatio);
|
||||
$gradC2: $bgBase;
|
||||
$cInvokeBase: lighten($gradC1, $ltnRatio*2);
|
||||
|
||||
@include background-image(linear-gradient($gradC1, $gradC2));
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border: none;
|
||||
border-top: 1px solid lighten($gradC1, 2%);
|
||||
color: $fg;
|
||||
display: inline-block;
|
||||
@if $hover == true {
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($gradC1, $hovRatio), lighten($gradC2, $hovRatio)));
|
||||
color: lighten($fgBase, $hovRatio);
|
||||
&.btn-menu .invoke-menu {
|
||||
color: lighten($cInvokeBase, $hovRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-menu .invoke-menu {
|
||||
color: $cInvokeBase;
|
||||
}
|
||||
@include background-image(linear-gradient($gradC1, $gradC2));
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border: none;
|
||||
border-top: 1px solid lighten($gradC1, 2%);
|
||||
color: $fg;
|
||||
display: inline-block;
|
||||
@if $hover == true {
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($gradC1, $hovRatio), lighten($gradC2, $hovRatio)));
|
||||
color: lighten($fgBase, $hovRatio);
|
||||
&.btn-menu .invoke-menu {
|
||||
color: lighten($cInvokeBase, $hovRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-menu .invoke-menu {
|
||||
color: $cInvokeBase;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
||||
@ -183,45 +188,45 @@
|
||||
}
|
||||
|
||||
@mixin controlGrippy($b, $direction: horizontal, $w: 1px, $style: dotted) {
|
||||
&:before {
|
||||
@include trans-prop-nice("border-color",0.75s);
|
||||
content: '';
|
||||
display: block;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
&:before {
|
||||
@include trans-prop-nice("border-color", 0.75s);
|
||||
content: '';
|
||||
display: block;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
|
||||
@if $direction == "horizontal" {
|
||||
border-top: $w $style darken($b, 15%);
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
@if $direction == "horizontal" {
|
||||
border-top: $w $style darken($b, 15%);
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
|
||||
} @else if $direction == "vertical" {
|
||||
border-left: $w $style darken($b, 15%);
|
||||
left: 2px;
|
||||
bottom: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
&:not(.disabled):hover:before {
|
||||
@include trans-prop-nice("border-color",50ms);
|
||||
border-color: $colorKey;
|
||||
}
|
||||
} @else if $direction == "vertical" {
|
||||
border-left: $w $style darken($b, 15%);
|
||||
left: 2px;
|
||||
bottom: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
&:not(.disabled):hover:before {
|
||||
@include trans-prop-nice("border-color", 50ms);
|
||||
border-color: $colorKey;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin btnSubtle($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include containerSubtle($bg, $fg, true);
|
||||
@include containerSubtle($bg, $fg, true);
|
||||
}
|
||||
|
||||
@mixin btnNoticeable($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
// No longer should be used; use btnSubtle instead
|
||||
//@include containerSubtle($bg, $fg, true);
|
||||
//@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
/* &:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
||||
}*/
|
||||
// No longer should be used; use btnSubtle instead
|
||||
//@include containerSubtle($bg, $fg, true);
|
||||
//@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
/* &:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
||||
}*/
|
||||
}
|
||||
|
||||
@mixin boxIncised($sVal: 0.6) {
|
||||
@ -237,59 +242,60 @@
|
||||
}
|
||||
|
||||
@mixin boxShdwLarge($sVal: 0.7) {
|
||||
@include box-shadow(rgba(black, $sVal) 0 3px 10px);
|
||||
@include box-shadow(rgba(black, $sVal) 0 3px 10px);
|
||||
}
|
||||
|
||||
@mixin outerGlow($color: #fff, $sVal: 0.3) {
|
||||
@include box-shadow(rgba($color, $sVal) 0 0 30px);
|
||||
@include box-shadow(rgba($color, $sVal) 0 0 30px);
|
||||
}
|
||||
|
||||
@mixin linearGlow($deg: 0, $c: red, $a: 0.4) {
|
||||
@include background-image(linear-gradient($deg, rgba($c,0), rgba($c, $a) 100%));
|
||||
@include background-image(linear-gradient($deg, rgba($c, 0), rgba($c, $a) 100%));
|
||||
}
|
||||
|
||||
@mixin subtleGrad($deg: 0, $c: red, $a0: 0.2, $a1: 0.3) {
|
||||
@include background-image(linear-gradient($deg, rgba($c,$a0), rgba($c, $a1) 100%));
|
||||
@include background-image(linear-gradient($deg, rgba($c, $a0), rgba($c, $a1) 100%));
|
||||
}
|
||||
|
||||
@mixin txtShdwSubtle($sVal: 0.1) {
|
||||
@include text-shadow(rgba(black, $sVal) 0 1px 2px);
|
||||
@include text-shadow(rgba(black, $sVal) 0 1px 2px);
|
||||
}
|
||||
|
||||
@mixin txtShdwLarge($sVal: 0.7) {
|
||||
@include text-shadow(rgba(black, $sVal) 0 3px 7px);
|
||||
@include text-shadow(rgba(black, $sVal) 0 3px 7px);
|
||||
}
|
||||
|
||||
/*********************************************** FORM ELEMENTS */
|
||||
@mixin input-base($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include appearance(none);
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include box-shadow(inset rgba(black, 0.65) 0 1px 4px);
|
||||
// background: lighten($bg, 20%);
|
||||
background: rgba(#fff, 0.1);
|
||||
border: none;
|
||||
//border-bottom: 1px solid rgba(#fff, 0.1);
|
||||
color: lighten($fg, 20%);
|
||||
outline: none;
|
||||
&.error {
|
||||
background: rgba(red, 0.5);
|
||||
}
|
||||
@include appearance(none);
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include box-shadow(inset rgba(black, 0.65) 0 1px 4px);
|
||||
// background: lighten($bg, 20%);
|
||||
background: rgba(#fff, 0.1);
|
||||
border: none;
|
||||
//border-bottom: 1px solid rgba(#fff, 0.1);
|
||||
color: lighten($fg, 20%);
|
||||
outline: none;
|
||||
&.error {
|
||||
background: rgba(red, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin nice-input($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include input-base($bg, $fg);
|
||||
padding: 0 $interiorMarginSm;
|
||||
@include input-base($bg, $fg);
|
||||
padding: 0 $interiorMarginSm;
|
||||
}
|
||||
|
||||
@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include input-base($bg, $fg);
|
||||
padding: $interiorMargin;
|
||||
@include input-base($bg, $fg);
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
|
||||
@mixin subdued-input($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include nice-input($bg, $fg);
|
||||
background: lighten($bg, 3%);
|
||||
border-bottom: 1px solid lighten($bg, 10%);
|
||||
@include nice-input($bg, $fg);
|
||||
background: lighten($bg, 3%);
|
||||
border-bottom: 1px solid lighten($bg, 10%);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -307,24 +313,40 @@
|
||||
padding: 0;
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin:0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin vertical-align {
|
||||
/* This doesn't work on an element inside an element with absolute positioning that has height: auto */
|
||||
position: relative;
|
||||
top: 50%;
|
||||
-webkit-transform: translateY(-50%);
|
||||
-ms-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
@mixin webkitProp($name, $val) {
|
||||
#{$name}: #{$val};
|
||||
-webkit-#{$name}: #{$val};
|
||||
}
|
||||
|
||||
@mixin webkitVal($name, $val) {
|
||||
#{$name}: #{$val};
|
||||
#{$name}: -webkit-#{$val};
|
||||
}
|
||||
|
||||
@mixin verticalCenter {
|
||||
/* This doesn't work on an element inside an element with absolute positioning that has height: auto */
|
||||
//position: relative;
|
||||
top: 50%;
|
||||
-webkit-transform: translateY(-50%);
|
||||
-ms-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
@mixin verticalCenterBlock($holderH, $itemH) {
|
||||
top: floor(($holderH - $itemH) / 2);
|
||||
bottom: auto;
|
||||
height: $itemH;
|
||||
}
|
||||
|
||||
@mixin ellipsize() {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@mixin scrollH($showBar: auto) {
|
||||
@ -338,21 +360,26 @@
|
||||
}
|
||||
|
||||
@mixin wait-spinner($b: 5px, $c: $colorAlt1) {
|
||||
display: block;
|
||||
position: absolute;
|
||||
-webkit-animation: rotation .6s infinite linear;
|
||||
-moz-animation: rotation .6s infinite linear;
|
||||
-o-animation: rotation .6s infinite linear;
|
||||
animation: rotation .6s infinite linear;
|
||||
border-color: rgba($c, 0.25);
|
||||
border-top-color: rgba($c, 1.0);
|
||||
border-style: solid;
|
||||
border-width: $b;
|
||||
border-radius: 100%;
|
||||
display: block;
|
||||
position: absolute;
|
||||
-webkit-animation: rotation .6s infinite linear;
|
||||
-moz-animation: rotation .6s infinite linear;
|
||||
-o-animation: rotation .6s infinite linear;
|
||||
animation: rotation .6s infinite linear;
|
||||
border-color: rgba($c, 0.25);
|
||||
border-top-color: rgba($c, 1.0);
|
||||
border-style: solid;
|
||||
border-width: $b;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
@mixin test($c: #ffcc00, $a: 0.2) {
|
||||
background-color: rgba($c, $a);
|
||||
background-color: rgba($c, $a);
|
||||
}
|
||||
|
||||
@mixin tmpBorder($c: #ffcc00, $a: 0.75) {
|
||||
@inlude box-sizing(border-box);
|
||||
border: 1px dotted rgba($c, $a);
|
||||
}
|
||||
|
||||
@mixin testObj($w: 2000px, $h: 1000px, $c: black, $a: 0.1) {
|
||||
@ -373,6 +400,6 @@
|
||||
}
|
||||
|
||||
@mixin s-stale($a: 0.5) {
|
||||
color: rgba($colorTelemFresh, $a) !important;
|
||||
font-style: italic;
|
||||
color: rgba($colorTelemFresh, $a) !important;
|
||||
font-style: italic;
|
||||
}
|
@ -26,7 +26,8 @@ $pad: $interiorMargin * $baseRatio;
|
||||
.btn,
|
||||
.l-btn {
|
||||
@include user-select(none);
|
||||
line-height: 1.5em; // Was 1.25em
|
||||
//line-height: 1.5em; // Was 1.25em
|
||||
line-height: 150%;
|
||||
padding: 0 $pad;
|
||||
text-decoration: none;
|
||||
&.lg,
|
||||
|
@ -102,7 +102,7 @@
|
||||
|
||||
.btn-bar {
|
||||
// position: relative;
|
||||
.btn,
|
||||
/* .btn,
|
||||
.btn-set,
|
||||
.t-btn {
|
||||
display: inline-block;
|
||||
@ -113,7 +113,7 @@
|
||||
&:first-child {
|
||||
// margin-left: 0;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.l-composite-control {
|
||||
@ -153,6 +153,7 @@
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
/*
|
||||
.btn-set {
|
||||
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
||||
display: inline-block;
|
||||
@ -171,37 +172,33 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
.object-browse-bar .btn,
|
||||
.object-browse-bar .t-btn,
|
||||
.object-browse-bar .view-switcher,
|
||||
.top-bar .buttons-main .btn,
|
||||
.top-bar .buttons-main .t-btn,
|
||||
.top-bar .view-switcher,
|
||||
.tool-bar .btn,
|
||||
.tool-bar .t-btn {
|
||||
$h: $btnToolbarH;
|
||||
display: inline-block;
|
||||
font-size: $h * $btnFontSizeToH;
|
||||
height: $h;
|
||||
line-height: $h - 3;
|
||||
.icon:not(.invoke-menu) {
|
||||
// position: relative;
|
||||
// top: -0.04em;
|
||||
//font-size: 150%;
|
||||
//vertical-align: middle;
|
||||
}
|
||||
line-height: 200%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
label.checkbox.custom {
|
||||
$bg: lighten($colorBodyBg, $ltGamma);
|
||||
$d: $formRowCtrlsH;
|
||||
// @include vertical-align();
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
line-height: $d;
|
||||
margin-right: $interiorMargin * 4;
|
||||
padding-left: $d + $interiorMargin;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
vertical-align: middle; // was top
|
||||
em {
|
||||
color: $colorBodyFg;
|
||||
display: inline-block;
|
||||
@ -326,9 +323,9 @@ label.checkbox.custom {
|
||||
$p: 10px;
|
||||
$badgeM: $interiorMargin;
|
||||
$badgeD: $h - ($badgeM * 2);
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
padding-right: 10px;
|
||||
//height: $h;
|
||||
//line-height: $h;
|
||||
//padding-right: 10px;
|
||||
&.browse-btn {
|
||||
margin-right: $interiorMargin;
|
||||
padding-left: $badgeD + $badgeM * 2;
|
||||
@ -351,7 +348,6 @@ label.checkbox.custom {
|
||||
.context-available {
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
//padding: 0 5px;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
@ -359,24 +355,63 @@ label.checkbox.custom {
|
||||
|
||||
.view-switcher {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
.type-icon {
|
||||
//vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** OBJECT-HEADER */
|
||||
.object-header {
|
||||
display: inline-block;
|
||||
//@include test();
|
||||
font-size: 1em;
|
||||
.label {
|
||||
.title-label {
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
}
|
||||
.type-icon {
|
||||
font-size: 120%;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: middle;
|
||||
|
||||
//> .title-label,
|
||||
//> .type-icon,
|
||||
//> .context-available {
|
||||
// //@include tmpBorder(#6666ff);
|
||||
// //vertical-align: middle;
|
||||
//}
|
||||
|
||||
> .type-icon {
|
||||
font-size: 120%;
|
||||
float: left;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.l-elem-wrapper {
|
||||
//@include test(#66f, 0.2);
|
||||
@include webkitProp(justify-content, flex-start);
|
||||
mct-representation {
|
||||
// Holds the context-available item
|
||||
// Must have min-width to make flex work properly
|
||||
// in Safari
|
||||
min-width: 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
.action {
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.title-label {
|
||||
//@include test(green, 0.9);
|
||||
@include ellipsize();
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
@include webkitProp(flex, '0 1 auto');
|
||||
padding-right: 0.35em; // For context arrow. Done with em's so pad is relative to the scale of the text.
|
||||
//position: relative;
|
||||
}
|
||||
|
||||
.context-available {
|
||||
font-size: 0.7em;
|
||||
@include webkitProp(flex, '0 0 1');
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
.context-available {
|
||||
@include trans-prop-nice(opacity, 0.25s);
|
||||
opacity: 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
&:hover {
|
||||
.context-available {
|
||||
@ -386,16 +421,6 @@ label.checkbox.custom {
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar,
|
||||
.object-browse-bar {
|
||||
.object-header {
|
||||
font-size: 1.1em;
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** SLIDERS */
|
||||
|
||||
.slider {
|
||||
@ -449,24 +474,26 @@ label.checkbox.custom {
|
||||
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
@include desktop {
|
||||
::-webkit-scrollbar {
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: rgba(#000, 0.4);
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: rgba(#000, 0.4);
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
.l-image-main-wrapper,
|
||||
.l-image-main,
|
||||
.l-image-main-controlbar,
|
||||
.l-image-main-controlbar .left,
|
||||
.l-image-main-controlbar .right,
|
||||
.l-image-thumbs-wrapper {
|
||||
@include absPosDefault(0, false);
|
||||
}
|
||||
@ -61,12 +59,9 @@
|
||||
.left {
|
||||
//@include test(red);
|
||||
text-align: left;
|
||||
width: 75% !important;
|
||||
}
|
||||
.right {
|
||||
//@include test(green);
|
||||
min-width: 40px;
|
||||
width: 25% !important;
|
||||
z-index: 2;
|
||||
}
|
||||
.l-date,
|
||||
|
@ -26,8 +26,10 @@
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "constants";
|
||||
@import "mobile/constants";
|
||||
@import "mixins";
|
||||
@import "forms/mixins";
|
||||
@import "mobile/mixins";
|
||||
@import "forms/elems";
|
||||
@import "forms/textarea";
|
||||
@import "forms/text-input";
|
||||
|
@ -20,47 +20,49 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.section-header {
|
||||
@include border-radius(3px);
|
||||
background: rgba(white, 0.1);
|
||||
@include border-radius($basicCr);
|
||||
background: rgba(#fff, 0.1);
|
||||
$c: lighten($colorBodyFg, 20%);
|
||||
//border-bottom: 1px solid rgba(#fff, 0.3);
|
||||
color: $c;
|
||||
font-size: 0.8em;
|
||||
margin-top: $interiorMargin;
|
||||
padding: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
padding: $formTBPad $formLRPad;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.form {
|
||||
// @include test(orange);
|
||||
.form-section {
|
||||
position: relative;
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
$m: $interiorMargin;
|
||||
@include box-sizing(border-box);
|
||||
@include clearfix;
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
margin-top: $interiorMargin;
|
||||
padding: $interiorMargin;
|
||||
border-top: 1px solid $colorFormLines;
|
||||
margin-top: $m;
|
||||
padding: $formTBPad 0;
|
||||
position: relative;
|
||||
&.first {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.label,
|
||||
.controls {
|
||||
// @include test(orange);
|
||||
>.label,
|
||||
>.controls {
|
||||
@include box-sizing(border-box);
|
||||
@include clearfix;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
line-height: $formInputH;
|
||||
min-height: $formInputH;
|
||||
}
|
||||
|
||||
>.label {
|
||||
// Only style this way for immediate children of .form-row; prevents problems when .label is used in .controls section of a form
|
||||
//@include test(orange, 0.05);
|
||||
float: left;
|
||||
min-width: 120px;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
width: $formLabelW;
|
||||
|
@ -25,18 +25,18 @@
|
||||
padding-right: $reqSymbolW + $reqSymbolM; // Keep room for validation element
|
||||
&::after {
|
||||
// @include test(yellow, 0.3);
|
||||
display: block;
|
||||
/* display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: $reqSymbolM;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: $reqSymbolW;
|
||||
width: $reqSymbolW;*/
|
||||
font-family: symbolsfont;
|
||||
font-size: $reqSymbolFontSize;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
//text-align: right;
|
||||
//vertical-align: middle;
|
||||
}
|
||||
}
|
||||
&.invalid,
|
||||
|
@ -75,15 +75,32 @@
|
||||
margin-left: $bubbleArwSize*2;
|
||||
.l-infobubble::before {
|
||||
right: 100%;
|
||||
@include triangle('left', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
// NOTE: [MOBILE] REMOVES TRIANGLE
|
||||
// Removes the triangle located on the info
|
||||
// bubble for phones only, for tablets and
|
||||
// desktops, triangle remains.
|
||||
@include desktopandtablet {
|
||||
@include triangle('left', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-right {
|
||||
margin-right: $bubbleArwSize*2;
|
||||
// NOTE: [MOBILE] REMOVES RIGHT MARGIN
|
||||
// Removes right margin made for the
|
||||
// triangle on mobile
|
||||
@include desktopandtablet {
|
||||
margin-right: $bubbleArwSize*2;
|
||||
}
|
||||
.l-infobubble::before {
|
||||
left: 100%;
|
||||
@include triangle('right', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
// NOTE: [MOBILE] REMOVES TRIANGLE
|
||||
// Removes the triangle located on the info
|
||||
// bubble for phones only, for tablets and
|
||||
// desktops, triangle remains.
|
||||
@include desktopandtablet {
|
||||
@include triangle('right', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,12 +139,12 @@
|
||||
//************************************************* LOOK AND FEEL
|
||||
|
||||
.l-thumbsbubble-wrapper {
|
||||
.arw-up {
|
||||
@include triangle('up', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
.arw-down {
|
||||
@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
.arw-up {
|
||||
@include triangle('up', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
.arw-down {
|
||||
@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
}
|
||||
|
||||
.s-infobubble {
|
||||
|
@ -26,5 +26,8 @@
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "constants";
|
||||
@import "mobile/constants";
|
||||
@import "mixins";
|
||||
@import "items/item";
|
||||
@import "mobile/mixins";
|
||||
@import "items/item";
|
||||
@import "mobile/item";
|
@ -44,7 +44,7 @@
|
||||
position: relative;
|
||||
&:hover .item-main {
|
||||
.item-type {
|
||||
color: $colorKey !important;
|
||||
color: lighten($colorKey, 10%) !important;
|
||||
.l-icon-link {
|
||||
color: $colorIconLink;
|
||||
}
|
||||
@ -55,13 +55,16 @@
|
||||
}
|
||||
}
|
||||
.contents {
|
||||
top: $interiorMargin; right: $interiorMargin; bottom: $interiorMargin; left: $interiorMargin;
|
||||
//@include test(red);
|
||||
$m: $interiorMarginLg;
|
||||
top: $m; right: $m; bottom: $m; left: $m;
|
||||
}
|
||||
.bar {
|
||||
&.top-bar.abs {
|
||||
&.top-bar {
|
||||
bottom: auto;
|
||||
height: $ueBrowseGridItemTopBarH;
|
||||
line-height: $ueBrowseGridItemTopBarH;
|
||||
text-align: right;
|
||||
z-index: 5;
|
||||
.left, .right {
|
||||
width: auto;
|
||||
@ -73,10 +76,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.bottom-bar.abs {
|
||||
&.bottom-bar {
|
||||
top: auto;
|
||||
height: $ueBrowseGridItemBottomBarH;
|
||||
padding: $interiorMargin;
|
||||
//height: $ueBrowseGridItemBottomBarH;
|
||||
line-height: 110%;
|
||||
}
|
||||
}
|
||||
.item-main {
|
||||
@ -89,7 +92,7 @@
|
||||
//@include trans-prop-nice("color", $transTime);
|
||||
@include absPosDefault($iconMargin, false);
|
||||
//@include test(red);
|
||||
color: $colorItemFg;
|
||||
//color: $colorItemFg;
|
||||
text-align: center;
|
||||
font-size: $iconD * 0.95; //6em;
|
||||
line-height: $iconD;
|
||||
@ -99,11 +102,12 @@
|
||||
//line-height: $lh;
|
||||
.l-icon-link {
|
||||
// When the link icon is in the item-type icon holder
|
||||
color: darken($colorIconLink, 25%);
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
//color: darken($colorIconLink, 25%);
|
||||
color: $colorIconLink;
|
||||
height: auto;
|
||||
line-height: 100%;
|
||||
position: absolute;
|
||||
font-size: 32px;
|
||||
font-size: 0.3em;
|
||||
left: 0px;
|
||||
bottom: 10px;
|
||||
z-index: 2;
|
||||
@ -123,13 +127,11 @@
|
||||
}
|
||||
.title {
|
||||
@include txtShdwSubtle();
|
||||
@include ellipsize();
|
||||
color: lighten($colorBodyFg, 20%);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
// font-weight: bold;
|
||||
}
|
||||
.details {
|
||||
@include ellipsize();
|
||||
font-size: 0.8em;
|
||||
}
|
||||
&.selected {
|
||||
|
86
platform/commonUI/general/res/sass/mobile/_constants.scss
Normal file
86
platform/commonUI/general/res/sass/mobile/_constants.scss
Normal file
@ -0,0 +1,86 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/************************** STYLE */
|
||||
$colorMobilePaneLeft: #222;
|
||||
|
||||
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
|
||||
$mobileListIconSize: 30px;
|
||||
$mobileTitleDescH: 35px;
|
||||
$mobileOverlayMargin: 10px;
|
||||
$phoneItemH: floor($ueBrowseGridItemLg/4);
|
||||
$tabletItemH: floor($ueBrowseGridItemLg/3);
|
||||
|
||||
/************************** MOBILE TREE MENU DIMENSIONS */
|
||||
$mobileTreeItemH: 35px;
|
||||
$mobileTreeItemIndent: 20px;
|
||||
$mobileTreeRightArrowW: 30px;
|
||||
|
||||
/************************** WINDOW DIMENSIONS FOR RWD */
|
||||
$phoMaxW: 514px;
|
||||
$phoMaxH: 740px;
|
||||
|
||||
$tabMinW: 515px;
|
||||
$tabMaxW: 799px;
|
||||
|
||||
$tabMinH: 741px;
|
||||
$tabMaxH: 1024px;
|
||||
|
||||
$compMinW: 800px;
|
||||
$compMinH: 1025px;
|
||||
|
||||
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
$screenPortrait: "screen and (orientation: portrait)";
|
||||
$screenLandscape: "screen and (orientation: landscape)";
|
||||
|
||||
$mobileDevice: "(max-device-width: #{$tabMaxW}) and (max-device-height: #{$tabMaxH})";
|
||||
$mobileDeviceEmu: "(max-device-width: #{$tabMaxH}) and (max-device-height: #{$tabMaxW})";
|
||||
|
||||
$phonePortraitCheck: "(max-width: #{$phoMaxW}) and (max-height: #{$phoMaxH})";
|
||||
$phoneLandscapeCheck: "(max-height: #{$phoMaxW}) and (max-width: #{$phoMaxH})";
|
||||
|
||||
$tabWidPorCheck: "(min-width: #{$tabMinW}) and (max-width: #{$tabMaxW})";
|
||||
$tabHeiPorCheck: "(min-height: #{$tabMinH}) and (max-height: #{$tabMaxH})";
|
||||
$tabletPortraitCheck: "#{$tabWidPorCheck} and #{$tabHeiPorCheck}";
|
||||
|
||||
$tabWidLanCheck: "(min-height: #{$tabMinW}) and (max-height: #{$tabMaxW})";
|
||||
$tabHeiLanCheck: "(min-width: #{$tabMinH}) and (max-width: #{$tabMaxH})";
|
||||
$tabletLandscapeCheck: "#{$tabWidLanCheck} and #{$tabHeiLanCheck}";
|
||||
|
||||
$desktopPortraitCheck: "(min-device-width: #{$compMinW}) and (min-device-height: #{$compMinH})";
|
||||
$desktopLandscapeCheck: "(min-device-width: #{$compMinH}) and (min-device-height: #{$compMinW})";
|
||||
|
||||
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
$phonePortrait: "#{$screenPortrait} and #{$phonePortraitCheck} and #{$mobileDevice}";
|
||||
$phoneLandscape: "#{$screenLandscape} and #{$phoneLandscapeCheck} and #{$mobileDevice}";
|
||||
$phoneLandscapeEmu: "#{$screenLandscape} and #{$phoneLandscapeCheck} and #{$mobileDeviceEmu}";
|
||||
|
||||
$tabletPortrait: "#{$screenPortrait} and #{$tabletPortraitCheck} and #{$mobileDevice}";
|
||||
$tabletLandscape: "#{$screenLandscape} and #{$tabletLandscapeCheck} and #{$mobileDevice}";
|
||||
$tabletLandscapeEmu: "#{$screenLandscape} and #{$tabletLandscapeCheck} and #{$mobileDeviceEmu}";
|
||||
|
||||
$desktopPortrait: "screen and #{$desktopPortraitCheck}";
|
||||
$desktopLandscape: "screen and #{$desktopLandscapeCheck}";
|
||||
|
||||
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
|
||||
$proporMenuOnly: 90%;
|
||||
$proporMenuWithView: 40%;
|
119
platform/commonUI/general/res/sass/mobile/_item.scss
Normal file
119
platform/commonUI/general/res/sass/mobile/_item.scss
Normal file
@ -0,0 +1,119 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Sets the size of the items in the folder
|
||||
// representation. Instead of a grid,
|
||||
// a list is used.
|
||||
|
||||
.items-holder {
|
||||
.item {
|
||||
&.grid-item {
|
||||
$titleH: 30px;
|
||||
@include phoneandtablet {
|
||||
width: 100%;
|
||||
>.contents {
|
||||
top: 0px; right: $interiorMarginLg; bottom: 0px; left: $interiorMarginLg;
|
||||
}
|
||||
.bar {
|
||||
&.top-bar {
|
||||
// Becomes the right side of the item
|
||||
//@include test(blue);
|
||||
bottom: 0 !important; left: auto !important; right: 20px !important;
|
||||
width: 40px !important; height: auto !important;
|
||||
text-align: right;
|
||||
}
|
||||
&.bottom-bar {
|
||||
// Becomes the left side of the item
|
||||
left: $mobileListIconSize + $interiorMarginLg;
|
||||
right: 60px;
|
||||
}
|
||||
|
||||
}
|
||||
.item-main {
|
||||
.item-type {
|
||||
//@include test(blue);
|
||||
font-size: $mobileListIconSize;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
line-height: 100%;
|
||||
text-align: left;
|
||||
width: $mobileListIconSize;
|
||||
.l-icon-link {
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.item-open {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
font-size: 1em;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include phone {
|
||||
$dHei: $phoneItemH;
|
||||
height: $dHei;
|
||||
.bar {
|
||||
&.top-bar {
|
||||
// Becomes the right side of the item
|
||||
line-height: $dHei !important;
|
||||
}
|
||||
&.bottom-bar {
|
||||
@include verticalCenterBlock($dHei, $mobileTitleDescH);
|
||||
}
|
||||
}
|
||||
.item-main {
|
||||
.item-type {
|
||||
@include verticalCenterBlock($dHei, $mobileListIconSize);
|
||||
}
|
||||
.item-open {
|
||||
line-height: $dHei;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include tablet {
|
||||
$dHei: $tabletItemH;
|
||||
height: $dHei;
|
||||
.bar {
|
||||
&.top-bar {
|
||||
// Becomes the right side of the item
|
||||
line-height: $dHei !important;
|
||||
}
|
||||
&.bottom-bar {
|
||||
@include verticalCenterBlock($dHei, $mobileTitleDescH);
|
||||
}
|
||||
}
|
||||
.item-main {
|
||||
.item-type {
|
||||
@include verticalCenterBlock($dHei, $mobileListIconSize);
|
||||
}
|
||||
.item-open {
|
||||
line-height: $dHei;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
platform/commonUI/general/res/sass/mobile/_layout.scss
Normal file
174
platform/commonUI/general/res/sass/mobile/_layout.scss
Normal file
@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
@include phoneandtablet {
|
||||
// Wrapper of the entire 2 panes, only enacted on
|
||||
// phone and tablet. Also for the panes
|
||||
.browse-wrapper,
|
||||
.pane {
|
||||
top: 0 !important; right: 0; bottom: 0; left: 0;
|
||||
}
|
||||
|
||||
.pane.left.treeview {
|
||||
background-color: $colorMobilePaneLeft;
|
||||
}
|
||||
|
||||
.pane.right-repr {
|
||||
//@include test();
|
||||
@include slMenuTransitions;
|
||||
margin-left: 0 !important;
|
||||
#content-area {
|
||||
@include slMenuTransitions;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.user-environ .browse-area,
|
||||
.user-environ .edit-area,
|
||||
.user-environ .editor {
|
||||
top: 0; left: 0; right: 0; bottom: $ueFooterH;
|
||||
}
|
||||
|
||||
.holder.l-mobile {
|
||||
top: $bodyMargin !important;
|
||||
right: $bodyMargin !important;
|
||||
bottom: $bodyMargin !important;
|
||||
left: $bodyMargin !important;
|
||||
}
|
||||
|
||||
// When the tree is hidden, these are the
|
||||
// classes used for the left menu and the
|
||||
// right representation.
|
||||
.browse-hidetree {
|
||||
@include user-select(none);
|
||||
// Sets the left tree menu when the tree
|
||||
// is hidden.
|
||||
.pane.left.treeview {
|
||||
opacity: 0;
|
||||
right: 100% !important;
|
||||
width: auto !important;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
// Sets the right represenation when
|
||||
// the tree is hidden.
|
||||
.pane.right-repr {
|
||||
left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.browse-showtree {
|
||||
// NOTE: DISABLED SELECTION
|
||||
// Selection disabled in both panes
|
||||
// causing cut/copy/paste menu to
|
||||
// not appear. Should me moved in
|
||||
// future to properly work
|
||||
@include user-select(none);
|
||||
|
||||
// Sets the left tree menu when the tree is shown.
|
||||
.pane.left.treeview {
|
||||
@include trans-prop-nice(opacity, .4s);
|
||||
@include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%));
|
||||
opacity: 1;
|
||||
display: block !important;
|
||||
//width: auto !important; // CH CO
|
||||
right: auto !important;
|
||||
width: $proporMenuWithView !important;
|
||||
}
|
||||
// Sets the right representation when the tree is shown.
|
||||
.pane.right-repr {
|
||||
left: $proporMenuWithView !important;
|
||||
//width: auto !important;
|
||||
|
||||
//left: 0 !important;
|
||||
//transform: translateX($proporMenuWithView);
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-menu-icon {
|
||||
font-size: 110%;
|
||||
position: absolute;
|
||||
top: $bodyMargin + 2;
|
||||
left: $bodyMargin;
|
||||
}
|
||||
|
||||
.object-browse-bar {
|
||||
//@include test();
|
||||
left: 30px !important;
|
||||
.context-available {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.view-switcher {
|
||||
margin-right: 0 !important;
|
||||
.name {
|
||||
// Hide the name in mobile
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-holder {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.mobile-disable-select {
|
||||
@include user-select(none);
|
||||
}
|
||||
|
||||
// Hides objects on phone and tablet
|
||||
.mobile-hide,
|
||||
.mobile-hide-important {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mobile-back-hide {
|
||||
pointer-events: none;
|
||||
@include trans-prop-nice(opacity, .4s);
|
||||
opacity: 0;
|
||||
}
|
||||
.mobile-back-unhide {
|
||||
pointer-events: all;
|
||||
@include trans-prop-nice(opacity, .4s);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@include phonePortrait {
|
||||
.browse-showtree {
|
||||
.pane.left.treeview {
|
||||
width: $proporMenuOnly !important;
|
||||
}
|
||||
.pane.right-repr {
|
||||
left: 0 !important;
|
||||
@include webkitProp(transform, translateX($proporMenuOnly));
|
||||
#content-area {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
.desktop-hide {
|
||||
display: none;
|
||||
}
|
||||
}
|
107
platform/commonUI/general/res/sass/mobile/_mixins.scss
Normal file
107
platform/commonUI/general/res/sass/mobile/_mixins.scss
Normal file
@ -0,0 +1,107 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Phones in any orientation
|
||||
@mixin phone {
|
||||
@media #{$phonePortrait},
|
||||
#{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
//Phones in portrait orientation
|
||||
@mixin phonePortrait {
|
||||
@media #{$phonePortrait} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Phones in landscape orientation
|
||||
@mixin phoneLandscape {
|
||||
@media #{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Tablets in any orientation
|
||||
@mixin tablet {
|
||||
@media #{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Tablets in portrait orientation
|
||||
@mixin tabletPortrait {
|
||||
@media #{$tabletPortrait} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Tablets in landscape orientation
|
||||
@mixin tabletLandscape {
|
||||
@media #{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Phones and tablets in any orientation
|
||||
@mixin phoneandtablet {
|
||||
@media #{$phonePortrait},
|
||||
#{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu},
|
||||
#{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop monitors in any orientation
|
||||
@mixin desktopandtablet {
|
||||
@media #{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu},
|
||||
#{$desktopPortrait},
|
||||
#{$desktopLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop monitors in any orientation
|
||||
@mixin desktop {
|
||||
@media #{$desktopPortrait},
|
||||
#{$desktopLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Transition used for the slide menu
|
||||
@mixin slMenuTransitions {
|
||||
@include transition-duration(.35s);
|
||||
transition-timing-function: ease;
|
||||
backface-visibility: hidden;
|
||||
}
|
@ -20,12 +20,38 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
// Overrides some styling in user-environ/_layout.scss
|
||||
.pane {
|
||||
&.treeview.left {
|
||||
.tree-holder {
|
||||
// Want tree holder to start right below the search bar.
|
||||
top: 60px;
|
||||
}
|
||||
@include phoneandtablet {
|
||||
ul.tree {
|
||||
// Sets the margin on the left, which causes the
|
||||
// running indentation after each folder is made
|
||||
ul.tree {
|
||||
margin-left: $mobileTreeItemIndent;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tree-item,
|
||||
.search-result-item {
|
||||
height: $mobileTreeItemH;
|
||||
line-height: $mobileTreeItemH;
|
||||
margin-bottom: 0px;
|
||||
.view-control {
|
||||
//@include test(red);
|
||||
position: absolute;
|
||||
font-size: 1.1em;
|
||||
right: 0px;
|
||||
width: $mobileTreeRightArrowW;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
left: 0;
|
||||
right: $mobileTreeRightArrowW + $interiorMargin; // Allows tree item name to stop prior to the arrow
|
||||
line-height: $mobileTreeItemH;
|
||||
//font-size: 1.1em; // CH CO
|
||||
.type-icon {
|
||||
@include verticalCenterBlock($mobileTreeItemH, $treeTypeIconH);
|
||||
}
|
||||
.title-label {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,12 +19,25 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.object-browse-bar {
|
||||
height: $ueTopBarH;
|
||||
line-height: $ueTopBarH;
|
||||
.items-select {
|
||||
.btn-menu {
|
||||
margin-right: $interiorMargin * 3;
|
||||
|
||||
// Override the Create menu for mobile
|
||||
@include phoneandtablet {
|
||||
.menu-element {
|
||||
.super-menu {
|
||||
$d: 250px;
|
||||
width: $d;
|
||||
height: $d;
|
||||
|
||||
.pane {
|
||||
&.left {
|
||||
border-right: none;
|
||||
padding-right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
&.right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
@include phoneandtablet {
|
||||
.overlay {
|
||||
$m: 0;
|
||||
.clk-icon.close {
|
||||
top: $mobileOverlayMargin; right: $mobileOverlayMargin;
|
||||
}
|
||||
|
||||
> .holder {
|
||||
@include border-radius($m);
|
||||
top: $m;
|
||||
right: $m;
|
||||
bottom: $m;
|
||||
left: $m;
|
||||
> .contents {
|
||||
top: $mobileOverlayMargin;
|
||||
right: $mobileOverlayMargin;
|
||||
bottom: $mobileOverlayMargin;
|
||||
left: $mobileOverlayMargin;
|
||||
|
||||
.top-bar {
|
||||
> .title {
|
||||
margin-right: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.form.editor {
|
||||
border: none;
|
||||
|
||||
.contents {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include phone {
|
||||
.overlay > .holder > .contents .form.editor .contents .form-row {
|
||||
> .label,
|
||||
> .controls {
|
||||
//@include test(blue);
|
||||
display: block;
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
@include phone {
|
||||
.search {
|
||||
.search-bar {
|
||||
// Hide menu-icon and adjust spacing when in phone mode
|
||||
.menu-icon {
|
||||
display: none;
|
||||
}
|
||||
.clear-icon {
|
||||
right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,16 +24,10 @@
|
||||
background: $colorOvrBlocker;
|
||||
z-index: 100;
|
||||
}
|
||||
.btn.close {
|
||||
@include border-radius($basicCr * 2);
|
||||
padding: 3px 6px;
|
||||
.clk-icon.close {
|
||||
position: absolute;
|
||||
border: none;
|
||||
top: $interiorMarginSm; right: $interiorMarginSm; bottom: auto; left: auto;
|
||||
top: $interiorMarginLg; right: $interiorMarginLg; bottom: auto; left: auto;
|
||||
z-index: 100;
|
||||
}
|
||||
.editor {
|
||||
// background: $colorBodyBg;
|
||||
}
|
||||
>.holder {
|
||||
$i: 15%;
|
||||
@ -43,13 +37,13 @@
|
||||
top: $i; right: $i; bottom: $i; left: $i;
|
||||
z-index: 101;
|
||||
>.contents {
|
||||
$m: 25px;
|
||||
$m: $overlayMargin;
|
||||
top: $m; right: $m; bottom: $m; left: $m;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@include ellipsize();
|
||||
font-size: 1.3em;
|
||||
font-size: 1.2em;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
height: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
//top: 23px;
|
||||
top: 23px;
|
||||
|
||||
// Align with the top of the divider bar, below create button
|
||||
//margin-top: 10px; // CH comment out
|
||||
@ -39,26 +39,20 @@
|
||||
$iconWidth: 20px;
|
||||
$leftMargin: 6px;
|
||||
$rightPadding: 5px;
|
||||
|
||||
//padding-right: $rightPadding;
|
||||
//@include test();
|
||||
display: flex; //block;
|
||||
flex-direction: column;
|
||||
@include webkitVal(display, flex);
|
||||
//display: flex;
|
||||
@include webkitProp(flex-direction, column);
|
||||
//flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.search-bar {
|
||||
//$heightAdjust: 4px;
|
||||
$textInputHeight: 19px; // This is equal to the default value, 19px
|
||||
$iconEdgeM: 4px;
|
||||
$iconD: $treeSearchInputBarH - ($iconEdgeM*2);
|
||||
font-size: 0.8em;
|
||||
|
||||
//order: 1;
|
||||
|
||||
max-width: 250px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
//height: $textInputHeight;
|
||||
//margin-top: $heightAdjust;
|
||||
.search-input,
|
||||
.search-icon {
|
||||
}
|
||||
@ -230,86 +224,6 @@
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
|
||||
.results {
|
||||
|
||||
.search-result-item {
|
||||
// Include transitions (for the highlights)
|
||||
@include single-transition(background-color, 0.25s);
|
||||
|
||||
// Space the results from each other
|
||||
margin-bottom: 2px;
|
||||
|
||||
// Make the highlights the right color and shape.
|
||||
// Attempting to match the style in the tree, but
|
||||
// while having these be compact.
|
||||
border-radius: 2px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 2px;
|
||||
|
||||
.label {
|
||||
// Give some padding away from the left side
|
||||
margin-left: $leftMargin;
|
||||
|
||||
.title-label {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
|
||||
// Give some padding away from the left side
|
||||
left: $leftMargin + 3px + $iconWidth;
|
||||
// and the right side
|
||||
right: $rightPadding;
|
||||
|
||||
// Size and position the text
|
||||
font-size: .8em;
|
||||
line-height: 17px;
|
||||
|
||||
// Hide overflow text
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// Change styling when it's selected
|
||||
&.selected {
|
||||
$c: #fff;
|
||||
background: $colorKeySelectedBg;
|
||||
color: $c;
|
||||
.view-control {
|
||||
color: $colorItemTreeIcon;
|
||||
}
|
||||
.label .type-icon {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.label .type-icon .l-icon-link {
|
||||
// Hide links for now. See GitHub issue #84.
|
||||
display: none;
|
||||
|
||||
@include txtShdwSubtle(1);
|
||||
z-index: 2;
|
||||
@include ancillaryIcon(8px, $colorIconLink);
|
||||
margin-left: -25px;
|
||||
}
|
||||
|
||||
// Change styling when it's being hovered over
|
||||
&:not(.selected) {
|
||||
&:hover {
|
||||
background: lighten($colorBodyBg, 5%);
|
||||
color: lighten($colorBodyFg, 20%);
|
||||
.context-trigger {
|
||||
display: block;
|
||||
}
|
||||
.icon {
|
||||
color: $colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.load-icon {
|
||||
position: relative;
|
||||
&.loading {
|
||||
|
@ -20,5 +20,6 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
@import "constants";
|
||||
@import "mobile/constants";
|
||||
@import "themes/theme-espresso";
|
||||
@import "main";
|
@ -19,4 +19,6 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* CONSTANTS */
|
||||
/* CONSTANTS */
|
||||
//$colorBodyBg: #fff;
|
||||
//$colorBodyFg: #666;
|
@ -21,11 +21,11 @@
|
||||
*****************************************************************************/
|
||||
@import "compass";
|
||||
@import "compass/css3";
|
||||
@import "compass/css3/border-radius";
|
||||
@import "compass/css3/opacity";
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "constants";
|
||||
@import "mobile/constants";
|
||||
@import "mixins";
|
||||
@import "mobile/mixins";
|
||||
@import "tree/tree";
|
||||
@import "search/search";
|
||||
@import "mobile/tree";
|
||||
|
@ -25,133 +25,152 @@ ul.tree {
|
||||
li {
|
||||
display: block;
|
||||
position: relative;
|
||||
span.tree-item {
|
||||
$runningItemW: 0;
|
||||
@include border-radius($basicCr);
|
||||
@include single-transition(background-color, 0.25s);
|
||||
}
|
||||
ul.tree {
|
||||
margin-left: $treeVCW + $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-item,
|
||||
.search-result-item {
|
||||
$runningItemW: 0;
|
||||
@include box-sizing(border-box);
|
||||
@include border-radius($basicCr);
|
||||
@include single-transition(background-color, 0.25s);
|
||||
display: block;
|
||||
font-size: 0.8rem;
|
||||
height: $menuLineH;
|
||||
line-height: $menuLineH;
|
||||
margin-bottom: $interiorMarginSm;
|
||||
position: relative;
|
||||
|
||||
.view-control {
|
||||
display: inline-block;
|
||||
margin-left: $interiorMargin;
|
||||
font-size: 0.75em;
|
||||
width: $treeVCW;
|
||||
$runningItemW: $interiorMargin + $treeVCW;
|
||||
// NOTE: [Mobile] Removed Hover on Mobile
|
||||
@include desktop {
|
||||
&:hover {
|
||||
color: $colorItemTreeVCHover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
// @include test(orange);
|
||||
@include absPosDefault();
|
||||
//left: $runningItemW + $interiorMargin; // Adding pad to left to make room for link icon
|
||||
line-height: $menuLineH;
|
||||
//left: $runningItemW;
|
||||
|
||||
.type-icon {
|
||||
//@include absPosDefault(0, false);
|
||||
$d: $treeTypeIconH; // 16px is crisp size
|
||||
@include txtShdwSubtle(0.6);
|
||||
font-size: $d;
|
||||
color: $colorItemTreeIcon;
|
||||
left: $interiorMargin;
|
||||
position: absolute;
|
||||
@include verticalCenterBlock($menuLineHPx, $d);
|
||||
line-height: 100%;
|
||||
right: auto; width: $d;
|
||||
|
||||
.icon {
|
||||
&.l-icon-link,
|
||||
&.l-icon-alert {
|
||||
@include txtShdwSubtle(1);
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
&.l-icon-alert {
|
||||
$d: 8px;
|
||||
@include ancillaryIcon($d, $colorAlert);
|
||||
top: 1px;
|
||||
right: -2px;
|
||||
}
|
||||
&.l-icon-link {
|
||||
$d: 8px;
|
||||
@include ancillaryIcon($d, $colorIconLink);
|
||||
left: -3px;
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title-label {
|
||||
@include absPosDefault();
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
height: $menuLineH;
|
||||
line-height: $menuLineH;
|
||||
margin-bottom: $interiorMarginSm;
|
||||
position: relative;
|
||||
left: $runningItemW + ($interiorMargin * 3);
|
||||
//right: $treeContextTriggerW + $interiorMargin;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.view-control {
|
||||
display: inline-block;
|
||||
margin-left: $interiorMargin;
|
||||
font-size: 0.75em;
|
||||
width: $treeVCW;
|
||||
$runningItemW: $interiorMargin + $treeVCW;
|
||||
&:hover {
|
||||
color: $colorItemTreeVCHover;
|
||||
}
|
||||
&.loading {
|
||||
pointer-events: none;
|
||||
.label {
|
||||
opacity: 0.5;
|
||||
.title-label {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
.wait-spinner {
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
// @include test(orange);
|
||||
@include absPosDefault();
|
||||
//left: $runningItemW + $interiorMargin; // Adding pad to left to make room for link icon
|
||||
left: $runningItemW;
|
||||
&.selected {
|
||||
$c: #fff;
|
||||
background: $colorKeySelectedBg;
|
||||
color: $c;
|
||||
.view-control {
|
||||
color: $colorItemTreeIcon;
|
||||
}
|
||||
.label .type-icon {
|
||||
color: #fff; //$colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
@include absPosDefault(0, false);
|
||||
@include txtShdwSubtle(0.6);
|
||||
color: $colorItemTreeIcon;
|
||||
left: $interiorMargin;
|
||||
right: auto; width: 1em;
|
||||
|
||||
.icon {
|
||||
&.l-icon-link,
|
||||
&.l-icon-alert {
|
||||
@include txtShdwSubtle(1);
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
&.l-icon-alert {
|
||||
$d: 8px;
|
||||
@include ancillaryIcon($d, $colorAlert);
|
||||
top: 1px;
|
||||
right: -2px;
|
||||
}
|
||||
&.l-icon-link {
|
||||
$d: 8px;
|
||||
@include ancillaryIcon($d, $colorIconLink);
|
||||
left: -3px;
|
||||
bottom: 5px;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.title-label {
|
||||
@include absPosDefault();
|
||||
&:not(.selected) {
|
||||
// NOTE: [Mobile] Removed Hover on Mobile
|
||||
@include desktop {
|
||||
&:hover {
|
||||
background: rgba(#fff, 0.1); //lighten($colorBodyBg, 5%);
|
||||
color: lighten($colorBodyFg, 20%);
|
||||
.context-trigger {
|
||||
display: block;
|
||||
left: $runningItemW + ($interiorMargin * 3);
|
||||
//right: $treeContextTriggerW + $interiorMargin;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&.loading {
|
||||
pointer-events: none;
|
||||
.label {
|
||||
opacity: 0.5;
|
||||
.title-label {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
.wait-spinner {
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
$c: #fff;
|
||||
background: $colorKeySelectedBg;
|
||||
color: $c;
|
||||
.view-control {
|
||||
color: $colorItemTreeIcon;
|
||||
}
|
||||
.label .type-icon {
|
||||
color: #fff; //$colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.selected) {
|
||||
&:hover {
|
||||
background: lighten($colorBodyBg, 5%);
|
||||
color: lighten($colorBodyFg, 20%);
|
||||
.context-trigger {
|
||||
display: block;
|
||||
}
|
||||
.icon {
|
||||
color: $colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.loading) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.context-trigger {
|
||||
$h: 0.9rem;
|
||||
//display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: $interiorMarginSm;
|
||||
.invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
.icon {
|
||||
color: $colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.tree {
|
||||
margin-left: $treeVCW + $interiorMargin;
|
||||
&:not(.loading) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.context-trigger {
|
||||
$h: 0.9rem;
|
||||
//display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: $interiorMarginSm;
|
||||
.invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-item {
|
||||
.label {
|
||||
left: $interiorMargin + $treeVCW;
|
||||
}
|
||||
}
|
@ -20,25 +20,23 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.frame {
|
||||
$ohH: 20px;
|
||||
$ohH: 16px;
|
||||
$bc: $colorInteriorBorder;
|
||||
&.child-frame.panel {
|
||||
background: $colorBodyBg;
|
||||
border: 1px solid $bc;
|
||||
&:hover {
|
||||
border-color: lighten($bc, 10%);
|
||||
//z-index: 2;
|
||||
}
|
||||
.contents {
|
||||
// overflow: hidden;
|
||||
}
|
||||
}
|
||||
>.object-header.abs {
|
||||
//@include test(red);
|
||||
font-size: 0.75em;
|
||||
height: $ohH;
|
||||
line-height: $ohH;
|
||||
}
|
||||
>.object-holder.abs {
|
||||
top: $ohH + $interiorMarginSm;
|
||||
top: $ohH + $interiorMargin;
|
||||
}
|
||||
.contents {
|
||||
$myM: $interiorMargin;
|
||||
@ -48,16 +46,20 @@
|
||||
left: $myM;
|
||||
}
|
||||
&.frame-template {
|
||||
// Hide the view switcher by default when it's in an element that's in a frame context
|
||||
// Frame template is used because we need to target the lowest nested frame
|
||||
.view-switcher {
|
||||
opacity: 0;
|
||||
line-height: $ohH;
|
||||
z-index: 10;
|
||||
}
|
||||
&:hover .view-switcher {
|
||||
// Show the view switcher on frame hover
|
||||
//display: inline-block !important;
|
||||
opacity: 1;
|
||||
// Hide the view switcher by default when it's in an element that's in a frame context
|
||||
// Frame template is used because we need to target the lowest nested frame
|
||||
@include desktop {
|
||||
.view-switcher {
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover .view-switcher {
|
||||
// Show the view switcher on frame hover
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.view-switcher {
|
||||
|
@ -70,19 +70,26 @@
|
||||
&.abs {
|
||||
text-wrap: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.left,
|
||||
.left {
|
||||
width: 45% !important;
|
||||
right: auto !important;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45% !important;
|
||||
left: auto !important;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
&.left,
|
||||
.left {
|
||||
width: 45%;
|
||||
right: auto;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45%;
|
||||
left: auto;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
}
|
||||
.l-flex,
|
||||
&.l-flex {
|
||||
.left,
|
||||
.right {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,7 +125,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
.ue-bottom-bar {
|
||||
//@include absPosDefault($bodyMargin);
|
||||
@include absPosDefault(0);// New status bar design
|
||||
top: auto;
|
||||
@ -200,7 +207,8 @@
|
||||
.split-layout {
|
||||
.split-pane-component.pane.left {
|
||||
min-width: 150px;
|
||||
max-width: 50%;
|
||||
max-width: 800px;
|
||||
width: $ueBrowseLeftPaneW;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,8 +216,8 @@
|
||||
.edit-mode {
|
||||
.split-layout {
|
||||
.split-pane-component.pane.right {
|
||||
min-width: 150px;
|
||||
max-width: 50%;
|
||||
//min-width: 150px;
|
||||
//max-width: 50%;
|
||||
.split-pane-component.pane.bottom {
|
||||
min-height: 50px;
|
||||
max-height: 80%;
|
||||
@ -243,6 +251,12 @@
|
||||
.right.abs {
|
||||
top: auto;
|
||||
}
|
||||
//.left.abs {
|
||||
// @include tmpBorder(green);
|
||||
//}
|
||||
//.right.abs {
|
||||
// @include tmpBorder(red);
|
||||
//}
|
||||
}
|
||||
.object-holder {
|
||||
top: $ueTopBarH + $interiorMarginLg;
|
||||
@ -267,6 +281,7 @@
|
||||
&.vertical {
|
||||
// Slides left and right
|
||||
>.pane {
|
||||
// @include test();
|
||||
margin-left: $interiorMargin;
|
||||
>.holder {
|
||||
left: 0;
|
||||
@ -283,6 +298,55 @@
|
||||
}
|
||||
}
|
||||
|
||||
.object-browse-bar .btn,
|
||||
.object-browse-bar .t-btn,
|
||||
.object-browse-bar .view-switcher,
|
||||
.top-bar .buttons-main .btn,
|
||||
.top-bar .buttons-main .t-btn,
|
||||
.top-bar .view-switcher,
|
||||
.tool-bar .btn,
|
||||
.tool-bar .t-btn {
|
||||
$h: $btnToolbarH;
|
||||
display: inline-block;
|
||||
font-size: $h * $btnFontSizeToH;
|
||||
line-height: 200%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.object-browse-bar,
|
||||
.top-bar {
|
||||
.view-switcher {
|
||||
margin-right: $interiorMarginLg * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.object-browse-bar {
|
||||
//@include test(blue);
|
||||
@include absPosDefault(0, visible);
|
||||
@include box-sizing(border-box);
|
||||
height: $ueTopBarH;
|
||||
line-height: $ueTopBarH;
|
||||
white-space: nowrap;
|
||||
|
||||
.left {
|
||||
padding-right: $interiorMarginLg * 2;
|
||||
.l-back {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin-right: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-flex {
|
||||
@include webkitVal('display', 'flex');
|
||||
@include webkitProp('flex-flow', 'row nowrap');
|
||||
.left {
|
||||
//@include test(red);
|
||||
@include webkitProp(flex, '1 1 0');
|
||||
}
|
||||
}
|
||||
|
||||
.vscroll {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
@ -20,23 +20,16 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.top-bar {
|
||||
// $h: $ueTopBarH - 5px;
|
||||
// background: rgba(#ff0000, 0.2);
|
||||
// line-height: $ueTopBarBtnH;
|
||||
|
||||
&.browse,
|
||||
&.edit {
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
top: $bodyMargin; right: $bodyMargin; bottom: auto; left: $bodyMargin;
|
||||
height: $ueTopBarEditH;
|
||||
line-height: $ueTopBarH;
|
||||
}
|
||||
|
||||
.action {
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #fff;
|
||||
// font-weight: bold;
|
||||
}
|
||||
|
||||
.buttons-main {
|
||||
@ -44,9 +37,9 @@
|
||||
left: auto;
|
||||
text-align: right;
|
||||
// width: 200px;
|
||||
.btn {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
// .btn {
|
||||
// margin-left: $interiorMargin;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='abs bottom-bar ue-bottom-bar' ng-controller="BottomBarController as bar">
|
||||
<div class='abs bottom-bar ue-bottom-bar mobile-disable-select' ng-controller="BottomBarController as bar">
|
||||
<div id='status' class='status-holder'>
|
||||
<mct-include ng-repeat="indicator in bar.getIndicators()"
|
||||
ng-model="indicator.ngModel"
|
||||
|
@ -21,7 +21,7 @@
|
||||
-->
|
||||
<span ng-controller="ViewSwitcherController">
|
||||
<div
|
||||
class="view-switcher menu-element btn btn-menu dropdown click-invoke"
|
||||
class="view-switcher menu-element s-btn l-btn btn-menu dropdown click-invoke"
|
||||
ng-if="view.length > 1"
|
||||
ng-controller="ClickAwayController as toggle"
|
||||
>
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="menu-element context-menu-wrapper" ng-controller="ContextMenuController">
|
||||
<div class="menu-element context-menu-wrapper mobile-disable-select" ng-controller="ContextMenuController">
|
||||
<div class="menu context-menu dropdown">
|
||||
<ul>
|
||||
|
||||
|
@ -22,23 +22,28 @@
|
||||
<span ng-controller="ToggleController as toggle">
|
||||
<span ng-controller="TreeNodeController as treeNode">
|
||||
<span
|
||||
class="tree-item menus-to-left"
|
||||
ng-class="{selected: treeNode.isSelected()}"
|
||||
>
|
||||
<span
|
||||
class='ui-symbol view-control'
|
||||
ng-click="toggle.toggle(); treeNode.trackExpansion()"
|
||||
ng-if="model.composition !== undefined"
|
||||
>
|
||||
{{toggle.isActive() ? "v" : ">"}}
|
||||
</span>
|
||||
class="tree-item menus-to-left"
|
||||
ng-class="{selected: treeNode.isSelected()}"
|
||||
>
|
||||
<mct-representation
|
||||
key="'label'"
|
||||
mct-object="domainObject"
|
||||
ng-model="ngModel"
|
||||
ng-click="!treeNode.checkMobile() || model.composition == undefined ||
|
||||
model.composition.length == 0 ? treeNode.setObject(ngModel, domainObject) : toggle.toggle();
|
||||
treeNode.trackExpansion()"
|
||||
>
|
||||
</mct-representation>
|
||||
<span
|
||||
class='ui-symbol view-control'
|
||||
mct-object="domainObject"
|
||||
ng-model="ngModel"
|
||||
ng-click="ngModel.selectedObject = domainObject"
|
||||
>
|
||||
</mct-representation>
|
||||
ng-click="treeNode.checkMobile() ? treeNode.setObject(ngModel, domainObject) :
|
||||
toggle.toggle(); treeNode.trackExpansion()"
|
||||
ng-if="model.composition !== undefined || treeNode.checkMobile()"
|
||||
>
|
||||
{{treeNode.checkMobile() ? "}" : toggle.isActive() ? "v" : ">"}}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="tree-item-subtree"
|
||||
|
@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise*/
|
||||
/*global define,Promise,window*/
|
||||
|
||||
/**
|
||||
* Module defining TreeNodeController. Created by vwoeltje on 11/10/14.
|
||||
@ -51,9 +51,11 @@ define(
|
||||
* @memberof platform/commonUI/general
|
||||
* @constructor
|
||||
*/
|
||||
function TreeNodeController($scope, $timeout) {
|
||||
function TreeNodeController($scope, $timeout, agentService) {
|
||||
var self = this,
|
||||
selectedObject = ($scope.ngModel || {}).selectedObject;
|
||||
selectedObject = ($scope.ngModel || {}).selectedObject,
|
||||
isSelected = false,
|
||||
hasBeenExpanded = false;
|
||||
|
||||
// Look up the id for a domain object. A convenience
|
||||
// for mapping; additionally does some undefined-checking.
|
||||
@ -75,7 +77,7 @@ define(
|
||||
((navPath[index] === nodePath[index]) &&
|
||||
checkPath(nodePath, navPath, index + 1));
|
||||
}
|
||||
|
||||
|
||||
// Consider the currently-navigated object and update
|
||||
// parameters which support display.
|
||||
function checkSelection() {
|
||||
@ -131,6 +133,8 @@ define(
|
||||
this.isSelectedFlag = false;
|
||||
this.hasBeenExpandedFlag = false;
|
||||
this.$timeout = $timeout;
|
||||
this.agentService = agentService;
|
||||
this.$scope = $scope;
|
||||
|
||||
// Listen for changes which will effect display parameters
|
||||
$scope.$watch("ngModel.selectedObject", setSelection);
|
||||
@ -172,6 +176,21 @@ define(
|
||||
TreeNodeController.prototype.isSelected = function () {
|
||||
return this.isSelectedFlag;
|
||||
};
|
||||
|
||||
// Sets the selected object in the tree, to be the
|
||||
// currently represented object. If the user is on phone
|
||||
// and in portrait mode, than, hide the tree menu
|
||||
TreeNodeController.prototype.setObject = function (ngModel, domainObject) {
|
||||
ngModel.selectedObject = domainObject;
|
||||
if (this.agentService.getOrientation(window.innerWidth, window.innerHeight) === "portrait" &&
|
||||
this.agentService.isPhone(navigator.userAgent)) {
|
||||
this.$scope.$emit('select-obj');
|
||||
}
|
||||
};
|
||||
|
||||
TreeNodeController.prototype.checkMobile = function () {
|
||||
return this.agentService.isMobile(navigator.userAgent);
|
||||
};
|
||||
|
||||
return TreeNodeController;
|
||||
}
|
||||
|
103
platform/commonUI/general/src/services/AgentService.js
Normal file
103
platform/commonUI/general/src/services/AgentService.js
Normal file
@ -0,0 +1,103 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
/**
|
||||
* Module defining AgentService.
|
||||
*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The query service handles calls for browser and userAgent
|
||||
* info using a comparison between the userAgent and key
|
||||
* device names
|
||||
*/
|
||||
function AgentService() {
|
||||
|
||||
// Gets the UA name if it is one of the following.
|
||||
// If it is not (a desktop for example) nothing is
|
||||
// returned instead
|
||||
function getDeviceUA(ua) {
|
||||
return ua.match(/iPad|iPhone|Android/i) ?
|
||||
ua.match(/iPad|iPhone|Android/i) : "";
|
||||
}
|
||||
|
||||
// Checks if gotten device is mobile,
|
||||
// Mobile is defined as a phone or tablet
|
||||
function isMobile(ua) {
|
||||
if (getDeviceUA(ua)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if device is phone,
|
||||
// phone is designated as only an
|
||||
// iPhone device
|
||||
function isPhone(ua) {
|
||||
if (getDeviceUA(ua)[0] === "iPhone") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the orientation of the device based on the
|
||||
// device's window dimensions, pass in the innerWidth
|
||||
// and innerheight of the current window
|
||||
function getOrientation(innerWidth, innerHeight) {
|
||||
if (innerWidth > innerHeight) {
|
||||
return "landscape";
|
||||
} else if (innerWidth < innerHeight) {
|
||||
return "portrait";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Returns the orientation for the user's device
|
||||
*/
|
||||
getOrientation: getOrientation,
|
||||
|
||||
/**
|
||||
* Returns the a boolean checking if the user is
|
||||
* on a mobile or non-mobile device. (mobile: true,
|
||||
* non-mobile: false)
|
||||
*/
|
||||
isMobile: isMobile,
|
||||
|
||||
/**
|
||||
* Returns the a boolean checking if the user is on
|
||||
* a phone device. (phone: true, non-phone: false)
|
||||
*/
|
||||
isPhone: isPhone
|
||||
};
|
||||
}
|
||||
|
||||
return AgentService;
|
||||
}
|
||||
);
|
@ -29,6 +29,9 @@ define(
|
||||
describe("The tree node controller", function () {
|
||||
var mockScope,
|
||||
mockTimeout,
|
||||
mockAgentService,
|
||||
mockNgModel,
|
||||
mockDomainObject,
|
||||
controller;
|
||||
|
||||
function TestObject(id, context) {
|
||||
@ -41,9 +44,19 @@ define(
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj("$scope", ["$watch", "$on"]);
|
||||
mockScope = jasmine.createSpyObj("$scope", ["$watch", "$on", "$emit"]);
|
||||
mockTimeout = jasmine.createSpy("$timeout");
|
||||
controller = new TreeNodeController(mockScope, mockTimeout);
|
||||
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile", "isPhone", "getOrientation"]);
|
||||
mockNgModel = jasmine.createSpyObj("ngModel", ["selectedObject"]);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
|
||||
mockAgentService.getOrientation.andReturn("portrait");
|
||||
mockAgentService.isPhone.andReturn(true);
|
||||
|
||||
controller = new TreeNodeController(mockScope, mockTimeout, mockAgentService);
|
||||
});
|
||||
|
||||
it("allows tracking of expansion state", function () {
|
||||
@ -183,6 +196,17 @@ define(
|
||||
expect(controller.isSelected()).toBeFalsy();
|
||||
|
||||
});
|
||||
|
||||
it("check if tree node is in a mobile device", function () {
|
||||
if (controller) {
|
||||
controller.checkMobile();
|
||||
}
|
||||
});
|
||||
|
||||
it("allows a set object to emit select-obj", function () {
|
||||
controller.setObject(mockNgModel, mockDomainObject);
|
||||
expect(mockScope.$emit).toHaveBeenCalledWith('select-obj');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
69
platform/commonUI/general/test/services/AgentServiceSpec.js
Normal file
69
platform/commonUI/general/test/services/AgentServiceSpec.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
/**
|
||||
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
||||
*/
|
||||
define(
|
||||
["../../src/services/AgentService"],
|
||||
function (AgentService) {
|
||||
"use strict";
|
||||
|
||||
describe("The url service", function () {
|
||||
var agentService,
|
||||
mockWindow,
|
||||
mockNavigator;
|
||||
|
||||
beforeEach(function () {
|
||||
// Creates a mockLocation, used to
|
||||
// do the view search
|
||||
mockWindow = jasmine.createSpyObj(
|
||||
"window",
|
||||
[ "innerWidth", "innerHeight" ]
|
||||
);
|
||||
|
||||
mockNavigator = jasmine.createSpyObj(
|
||||
"navigator",
|
||||
[ "userAgent" ]
|
||||
);
|
||||
|
||||
agentService = new AgentService();
|
||||
});
|
||||
|
||||
it("get current device user agent", function () {
|
||||
mockNavigator.userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36";
|
||||
agentService.isMobile(mockNavigator.userAgent);
|
||||
agentService.isPhone(mockNavigator.userAgent);
|
||||
mockNavigator.userAgent = "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53";
|
||||
agentService.isMobile(mockNavigator.userAgent);
|
||||
mockNavigator.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53";
|
||||
agentService.isPhone(mockNavigator.userAgent);
|
||||
});
|
||||
|
||||
it("get orientation of the current device", function () {
|
||||
agentService.getOrientation(1024, 768);
|
||||
agentService.getOrientation(768, 1024);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -91,7 +91,7 @@ define(
|
||||
|
||||
it("get url for a new tab using domainObject and mode", function () {
|
||||
urlService.urlForNewTab(mockMode, mockDomainObject);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -13,6 +13,7 @@
|
||||
"directives/MCTDrag",
|
||||
"directives/MCTResize",
|
||||
"directives/MCTScroll",
|
||||
"services/AgentService",
|
||||
"services/UrlService",
|
||||
"StyleSheetLoader"
|
||||
]
|
@ -24,9 +24,19 @@
|
||||
"implementation": "gestures/InfoGesture.js",
|
||||
"depends": [
|
||||
"$timeout",
|
||||
"agentService",
|
||||
"infoService",
|
||||
"INFO_HOVER_DELAY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "infobutton",
|
||||
"implementation": "gestures/InfoButtonGesture.js",
|
||||
"depends": [
|
||||
"$document",
|
||||
"agentService",
|
||||
"infoService"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
@ -37,15 +47,23 @@
|
||||
"$compile",
|
||||
"$document",
|
||||
"$window",
|
||||
"$rootScope"
|
||||
"$rootScope",
|
||||
"agentService"
|
||||
]
|
||||
}
|
||||
],
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "INFO_HOVER_DELAY",
|
||||
"value": 2000
|
||||
}
|
||||
],
|
||||
"representations": [
|
||||
{
|
||||
"key": "info-button",
|
||||
"templateUrl": "templates/info-button.html",
|
||||
"gestures": [ "infobutton" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
25
platform/commonUI/inspect/res/templates/info-button.html
Normal file
25
platform/commonUI/inspect/res/templates/info-button.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!--The icon for the info button appearing in a grid item (list in folder)-->
|
||||
<a class='ui-symbol icon mobile-info'></a>
|
||||
|
123
platform/commonUI/inspect/src/gestures/InfoButtonGesture.js
Normal file
123
platform/commonUI/inspect/src/gestures/InfoButtonGesture.js
Normal file
@ -0,0 +1,123 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The `info` gesture displays domain object metadata in a
|
||||
* bubble on hover.
|
||||
*
|
||||
* @constructor
|
||||
* @param $document Angular's `$document`
|
||||
* @param {InfoService} infoService a service which shows info bubbles
|
||||
* @param element jqLite-wrapped DOM element
|
||||
* @param {DomainObject} domainObject the domain object for which to
|
||||
* show information
|
||||
*/
|
||||
function InfoGestureButton($document, agentService, infoService, element, domainObject) {
|
||||
var dismissBubble,
|
||||
touchPosition,
|
||||
scopeOff,
|
||||
body = $document.find('body');
|
||||
|
||||
function trackPosition(event) {
|
||||
// Record touch position, so bubble can be shown at latest
|
||||
// touch position, also offset by 22px to left (accounts for
|
||||
// a finger-sized touch on the info button)
|
||||
touchPosition = [ event.clientX - 22, event.clientY ];
|
||||
}
|
||||
|
||||
// Hides the bubble and detaches the
|
||||
// body hidebubble listener
|
||||
function hideBubble() {
|
||||
// If a bubble is showing, dismiss it
|
||||
if (dismissBubble) {
|
||||
dismissBubble();
|
||||
dismissBubble = undefined;
|
||||
}
|
||||
|
||||
// Detaches body touch listener
|
||||
body.off('touchstart', hideBubble);
|
||||
}
|
||||
|
||||
// Displays the bubble by tracking position of
|
||||
// touch, using infoService to display the bubble,
|
||||
// and then on any body touch the bubble is dismissed
|
||||
function showBubble(event) {
|
||||
trackPosition(event);
|
||||
event.stopPropagation();
|
||||
// Show the bubble, but on any touchstart on the
|
||||
// body (anywhere) call hidebubble
|
||||
dismissBubble = infoService.display(
|
||||
"info-table",
|
||||
domainObject.getModel().name,
|
||||
domainObject.useCapability('metadata'),
|
||||
touchPosition
|
||||
);
|
||||
|
||||
// On any touch on the body, default body touches/events
|
||||
// are prevented, the bubble is dismissed, and the touchstart
|
||||
// body event is unbound, reallowing gestures
|
||||
body.on('touchstart', function (event) {
|
||||
event.preventDefault();
|
||||
hideBubble();
|
||||
body.unbind('touchstart');
|
||||
});
|
||||
}
|
||||
|
||||
// Checks if you are on a mobile device, if the device is
|
||||
// mobile (agentService.isMobile() = true), then
|
||||
// the a click on something (info button) brings up
|
||||
// the bubble
|
||||
if (agentService.isMobile(navigator.userAgent)) {
|
||||
element.on('click', showBubble);
|
||||
}
|
||||
|
||||
// Also make sure we dismiss bubble if representation is destroyed
|
||||
// before the mouse actually leaves it
|
||||
scopeOff = element.scope().$on('$destroy', hideBubble);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Detach any event handlers associated with this gesture.
|
||||
* @memberof InfoGesture
|
||||
* @method
|
||||
*/
|
||||
destroy: function () {
|
||||
// Dismiss any active bubble...
|
||||
hideBubble();
|
||||
// ...and detach listeners
|
||||
element.off('click', showBubble);
|
||||
scopeOff();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return InfoGestureButton;
|
||||
|
||||
}
|
||||
|
||||
);
|
@ -40,7 +40,7 @@ define(
|
||||
* @param {DomainObject} domainObject the domain object for which to
|
||||
* show information
|
||||
*/
|
||||
function InfoGesture($timeout, infoService, delay, element, domainObject) {
|
||||
function InfoGesture($timeout, agentService, infoService, delay, element, domainObject) {
|
||||
var self = this;
|
||||
|
||||
// Callback functions to preserve the "this" pointer (in the
|
||||
@ -64,9 +64,14 @@ define(
|
||||
this.infoService = infoService;
|
||||
this.delay = delay;
|
||||
this.domainObject = domainObject;
|
||||
|
||||
// Show bubble (on a timeout) on mouse over
|
||||
element.on('mouseenter', this.showBubbleCallback);
|
||||
|
||||
// Checks if you are on a mobile device, if the device is
|
||||
// not mobile (agentService.isMobile() = false), then
|
||||
// the pendingBubble and therefore hovering is allowed
|
||||
if (!agentService.isMobile(navigator.userAgent)) {
|
||||
// Show bubble (on a timeout) on mouse over
|
||||
element.on('mouseenter', this.showBubbleCallback);
|
||||
}
|
||||
}
|
||||
|
||||
InfoGesture.prototype.trackPosition = function (event) {
|
||||
@ -93,7 +98,7 @@ define(
|
||||
// arrays allocated while user mouses over things
|
||||
this.mousePosition = undefined;
|
||||
};
|
||||
|
||||
|
||||
InfoGesture.prototype.showBubble = function (event) {
|
||||
var self = this;
|
||||
|
||||
@ -117,6 +122,7 @@ define(
|
||||
|
||||
this.element.on('mouseleave', this.hideBubbleCallback);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detach any event handlers associated with this gesture.
|
||||
|
@ -34,11 +34,12 @@ define(
|
||||
* @memberof platform/commonUI/inspect
|
||||
* @constructor
|
||||
*/
|
||||
function InfoService($compile, $document, $window, $rootScope) {
|
||||
function InfoService($compile, $document, $window, $rootScope, agentService) {
|
||||
this.$compile = $compile;
|
||||
this.$document = $document;
|
||||
this.$window = $window;
|
||||
this.$rootScope = $rootScope;
|
||||
this.agentService = agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,12 +65,12 @@ define(
|
||||
goLeft = position[0] > (winDim[0] - bubbleSpaceLR),
|
||||
goUp = position[1] > (winDim[1] / 2),
|
||||
bubble;
|
||||
|
||||
|
||||
// Pass model & container parameters into the scope
|
||||
scope.bubbleModel = content;
|
||||
scope.bubbleTemplate = templateKey;
|
||||
scope.bubbleLayout = (goUp ? 'arw-btm' : 'arw-top') + ' ' +
|
||||
(goLeft ? 'arw-right' : 'arw-left');
|
||||
(goLeft ? 'arw-right' : 'arw-left');
|
||||
scope.bubbleTitle = title;
|
||||
|
||||
// Create the context menu
|
||||
@ -77,15 +78,22 @@ define(
|
||||
|
||||
// Position the bubble
|
||||
bubble.css('position', 'absolute');
|
||||
if (goLeft) {
|
||||
bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
|
||||
if (this.agentService.isPhone(navigator.userAgent)) {
|
||||
bubble.css('right', '0px');
|
||||
bubble.css('left', '0px');
|
||||
bubble.css('top', 'auto');
|
||||
bubble.css('bottom', '25px');
|
||||
} else {
|
||||
bubble.css('left', position[0] + OFFSET[0] + 'px');
|
||||
}
|
||||
if (goUp) {
|
||||
bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
|
||||
} else {
|
||||
bubble.css('top', position[1] + OFFSET[1] + 'px');
|
||||
if (goLeft) {
|
||||
bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
|
||||
} else {
|
||||
bubble.css('left', position[0] + OFFSET[0] + 'px');
|
||||
}
|
||||
if (goUp) {
|
||||
bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
|
||||
} else {
|
||||
bubble.css('top', position[1] + OFFSET[1] + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
// Add the menu to the body
|
||||
|
145
platform/commonUI/inspect/test/gestures/InfoButtonGestureSpec.js
Normal file
145
platform/commonUI/inspect/test/gestures/InfoButtonGestureSpec.js
Normal file
@ -0,0 +1,145 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
define(
|
||||
['../../src/gestures/InfoButtonGesture'],
|
||||
function (InfoButtonGesture) {
|
||||
"use strict";
|
||||
|
||||
describe("The info button gesture", function () {
|
||||
var mockTimeout,
|
||||
mockDocument,
|
||||
mockBody,
|
||||
mockAgentService,
|
||||
mockInfoService,
|
||||
mockElement,
|
||||
mockDomainObject,
|
||||
mockEvent,
|
||||
mockScope,
|
||||
mockOff,
|
||||
testMetadata,
|
||||
mockPromise,
|
||||
mockHide,
|
||||
gesture,
|
||||
fireGesture,
|
||||
fireDismissGesture;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy('$timeout');
|
||||
mockDocument = jasmine.createSpyObj('$document', ['find']);
|
||||
mockBody = jasmine.createSpyObj('body', [ 'on', 'off', 'scope', 'css', 'unbind' ]);
|
||||
mockDocument.find.andReturn(mockBody);
|
||||
mockAgentService = jasmine.createSpyObj('agentService', ['isMobile', 'isPhone']);
|
||||
mockInfoService = jasmine.createSpyObj(
|
||||
'infoService',
|
||||
[ 'display' ]
|
||||
);
|
||||
mockElement = jasmine.createSpyObj(
|
||||
'element',
|
||||
[ 'on', 'off', 'scope', 'css' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getId', 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
|
||||
mockEvent = jasmine.createSpyObj("event", ["preventDefault", "stopPropagation"]);
|
||||
mockEvent.pageX = 0;
|
||||
mockEvent.pageY = 0;
|
||||
mockScope = jasmine.createSpyObj('$scope', [ '$on' ]);
|
||||
mockOff = jasmine.createSpy('$off');
|
||||
testMetadata = [ { name: "Test name", value: "Test value" } ];
|
||||
mockHide = jasmine.createSpy('hide');
|
||||
|
||||
mockDomainObject.getModel.andReturn({ name: "Test Object" });
|
||||
mockDomainObject.useCapability.andCallFake(function (c) {
|
||||
return (c === 'metadata') ? testMetadata : undefined;
|
||||
});
|
||||
mockElement.scope.andReturn(mockScope);
|
||||
mockScope.$on.andReturn(mockOff);
|
||||
mockInfoService.display.andReturn(mockHide);
|
||||
mockAgentService.isMobile.andReturn(true);
|
||||
gesture = new InfoButtonGesture(
|
||||
mockDocument,
|
||||
mockAgentService,
|
||||
mockInfoService,
|
||||
mockElement,
|
||||
mockDomainObject
|
||||
);
|
||||
fireGesture = mockElement.on.mostRecentCall.args[1];
|
||||
});
|
||||
|
||||
it("expect click on the representation", function () {
|
||||
// Fires a click call on element and then
|
||||
// expects the click to have happened
|
||||
fireGesture(mockEvent);
|
||||
expect(mockElement.on).toHaveBeenCalledWith(
|
||||
"click",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("expect click then dismiss on the representation", function () {
|
||||
// Fire the click and then expect the click
|
||||
fireGesture(mockEvent);
|
||||
expect(mockElement.on).toHaveBeenCalledWith(
|
||||
"click",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
// Get the touch start on the body
|
||||
// and fire the dismiss gesture
|
||||
fireDismissGesture = mockBody.on.mostRecentCall.args[1];
|
||||
fireDismissGesture(mockEvent);
|
||||
// Expect Body to have been touched, event.preventDefault()
|
||||
// to be called, then the mockBody listener to be detached
|
||||
// lastly unbind the touchstart used to dismiss so other
|
||||
// events can be called
|
||||
expect(mockBody.on).toHaveBeenCalledWith(
|
||||
"touchstart",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
||||
expect(mockBody.off).toHaveBeenCalledWith(
|
||||
"touchstart",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(mockBody.unbind).toHaveBeenCalledWith(
|
||||
'touchstart'
|
||||
);
|
||||
});
|
||||
|
||||
it("detaches a callback for info bubble events when destroyed", function () {
|
||||
expect(mockElement.off).not.toHaveBeenCalled();
|
||||
|
||||
gesture.destroy();
|
||||
|
||||
expect(mockElement.off).toHaveBeenCalledWith(
|
||||
"click",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -28,6 +28,7 @@ define(
|
||||
|
||||
describe("The info gesture", function () {
|
||||
var mockTimeout,
|
||||
mockAgentService,
|
||||
mockInfoService,
|
||||
testDelay = 12321,
|
||||
mockElement,
|
||||
@ -50,6 +51,7 @@ define(
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy('$timeout');
|
||||
mockTimeout.cancel = jasmine.createSpy('cancel');
|
||||
mockAgentService = jasmine.createSpyObj('agentService', ['isMobile']);
|
||||
mockInfoService = jasmine.createSpyObj(
|
||||
'infoService',
|
||||
[ 'display' ]
|
||||
@ -79,6 +81,7 @@ define(
|
||||
|
||||
gesture = new InfoGesture(
|
||||
mockTimeout,
|
||||
mockAgentService,
|
||||
mockInfoService,
|
||||
testDelay,
|
||||
mockElement,
|
||||
|
@ -31,6 +31,7 @@ define(
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope,
|
||||
mockAgentService,
|
||||
mockCompiledTemplate,
|
||||
testScope,
|
||||
mockBody,
|
||||
@ -42,6 +43,7 @@ define(
|
||||
mockDocument = jasmine.createSpyObj('$document', ['find']);
|
||||
testWindow = { innerWidth: 1000, innerHeight: 100 };
|
||||
mockRootScope = jasmine.createSpyObj('$rootScope', ['$new']);
|
||||
mockAgentService = jasmine.createSpyObj('agentService', ['isMobile', 'isPhone']);
|
||||
mockCompiledTemplate = jasmine.createSpy('template');
|
||||
testScope = {};
|
||||
mockBody = jasmine.createSpyObj('body', ['append']);
|
||||
@ -58,7 +60,8 @@ define(
|
||||
mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope
|
||||
mockRootScope,
|
||||
mockAgentService
|
||||
);
|
||||
});
|
||||
|
||||
@ -124,6 +127,18 @@ define(
|
||||
(40 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("when on phone device, positioning is always on bottom", function () {
|
||||
mockAgentService.isPhone.andReturn(true);
|
||||
service = new InfoService(
|
||||
mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope,
|
||||
mockAgentService
|
||||
);
|
||||
service.display('', '', {}, [0, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
[
|
||||
"gestures/InfoGesture",
|
||||
"gestures/InfoButtonGesture",
|
||||
"services/InfoService"
|
||||
]
|
||||
|
@ -117,12 +117,6 @@
|
||||
"pattern": "\\S+",
|
||||
"required": true,
|
||||
"cssclass": "l-med"
|
||||
},
|
||||
{
|
||||
"control": "checkbox",
|
||||
"name": "Display title by default",
|
||||
"key": "displayTitle",
|
||||
"property": [ "display", "title" ]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -142,7 +136,11 @@
|
||||
{
|
||||
"key": "unknown",
|
||||
"name": "Unknown Type",
|
||||
"glyph": "?"
|
||||
"glyph": "\u003f"
|
||||
},
|
||||
{
|
||||
"name": "Unknown Type",
|
||||
"glyph": "\u003f"
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
|
@ -33,7 +33,7 @@
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="l-image-main-controlbar bar">
|
||||
<div class="l-image-main-controlbar l-flex bar">
|
||||
<div class="left">
|
||||
<a
|
||||
class="t-btn l-btn s-btn s-icon-btn s-very-subtle show-thumbs sm"
|
||||
|
@ -20,13 +20,12 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="frame frame-template abs">
|
||||
<div class="bar abs object-header object-top-bar">
|
||||
<div class="title left abs">
|
||||
<mct-representation key="'node'"
|
||||
mct-object="domainObject">
|
||||
<div class="bar abs l-flex object-header object-top-bar">
|
||||
<div class="left">
|
||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="btn-bar right abs">
|
||||
<div class="btn-bar right">
|
||||
<mct-representation key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
|
57
platform/features/plot-reborn/README.md
Normal file
57
platform/features/plot-reborn/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# plot-reborn
|
||||
|
||||
The `plot-reborn` bundle provides directives for composing plot based views.
|
||||
It also exposes domain objects for plotting telemetry points.
|
||||
|
||||
## Views
|
||||
|
||||
* OverlayPlot: can be used on any domain object that has or delegates a
|
||||
telemetry capability.
|
||||
|
||||
* StackedPlot: can be used on any domain object that delegates telemetry or
|
||||
delegates composition of elements that have telemetry.
|
||||
|
||||
## Directives
|
||||
|
||||
* `mct-chart`: an element that takes `series`, `viewport`, and
|
||||
`rectangles` and plots the data. Adding points to a series after it has
|
||||
been initially plotted can be done either by recreating the series object
|
||||
or by broadcasting "series:data:add" with arguments `event`, `seriesIndex`,
|
||||
`points`. This will append `points` to the `series` at index `seriesIndex`.
|
||||
|
||||
* `mct-plot`: A directive that wraps a mct-chart and handles user interactions
|
||||
with that plot. It emits events that a parent view can use for coordinating
|
||||
functionality:
|
||||
* emits a `user:viewport:change:start` event when the viewport begins being
|
||||
changed by a user, to allow any parent controller to prevent viewport
|
||||
modifications while the user is interacting with the plot.
|
||||
* emits a `user:viewport:change:end` event when the user has finished
|
||||
changing the viewport. This allows a controller on a parent scope to
|
||||
track viewport history and provide any necessary functionality
|
||||
around viewport changes, e.g. viewport history.
|
||||
|
||||
* `mct-overlay-plot`: A directive that takes `domainObject` and plots either a
|
||||
single series of data (in the case of a single telemetry object) or multiple
|
||||
series of data (in the case of a object which delegates telemetry).
|
||||
|
||||
## Controllers
|
||||
|
||||
NOTE: this section not accurate. Essentially, these controllers format data for
|
||||
the mct-chart directive. They also handle live viewport updating, as well as
|
||||
managing all transformations from domain objects to views.
|
||||
|
||||
* StackPlotController: Uses the composition capability of a StackPlot domain
|
||||
object to retrieve SubPlots and render them with individual PlotControllers.
|
||||
* PlotController: Uses either a domain object that delegates telemetry or a
|
||||
domain object with telemetry to and feeds that data to the mct-chart
|
||||
directive.
|
||||
|
||||
## TODOS:
|
||||
|
||||
* [ ] Re-implement history stack.
|
||||
* [ ] Re-implement plot pallette.
|
||||
* [ ] Re-implement stacked plot viewport synchronization (share viewport object)
|
||||
* [ ] Other things?
|
||||
* [ ] Handle edge cases with marquee zoom/panning.
|
||||
* [ ] Tidy code.
|
||||
|
101
platform/features/plot-reborn/bundle.json
Normal file
101
platform/features/plot-reborn/bundle.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"name": "Plot view for telemetry, reborn",
|
||||
"extensions": {
|
||||
"views": [
|
||||
{
|
||||
"name": "Plot",
|
||||
"key": "plot-single",
|
||||
"glyph": "6",
|
||||
"templateUrl": "templates/plot.html",
|
||||
"needs": ["telemetry"],
|
||||
"uses": ["composition"],
|
||||
"delegation": false
|
||||
},
|
||||
{
|
||||
"name": "Overlay Plot",
|
||||
"key": "plot",
|
||||
"glyph": "6",
|
||||
"templateUrl": "templates/plot.html",
|
||||
"needs": ["telemetry", "composition"],
|
||||
"uses": ["composition"],
|
||||
"delegation": true
|
||||
},
|
||||
{
|
||||
"name": "Stacked Plot",
|
||||
"key": "stackedPlot",
|
||||
"glyph": "6",
|
||||
"templateUrl": "templates/stacked-plot.html",
|
||||
"needs": ["composition", "delegation"],
|
||||
"uses": ["composition"],
|
||||
"gestures": [ "drop" ],
|
||||
"delegation": true
|
||||
}
|
||||
],
|
||||
"directives": [
|
||||
{
|
||||
"key": "mctChart",
|
||||
"implementation": "directives/MCTChart.js",
|
||||
"depends": [ "$interval", "agentService" ]
|
||||
},
|
||||
{
|
||||
"key": "mctPlot",
|
||||
"implementation": "directives/MCTPlot.js",
|
||||
"depends": [],
|
||||
"templateUrl": "templates/mct-plot.html"
|
||||
},
|
||||
{
|
||||
"key": "mctOverlayPlot",
|
||||
"implementation": "directives/MCTOverlayPlot.js",
|
||||
"depends": []
|
||||
},
|
||||
{
|
||||
"key": "mctPinch",
|
||||
"implementation": "directives/MCTPinch.js",
|
||||
"depends": [ "agentService" ]
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "PlotController",
|
||||
"implementation": "controllers/PlotController.js",
|
||||
"depends": [ "$scope", "colorService", "agentService"]
|
||||
},
|
||||
{
|
||||
"key": "StackedPlotController",
|
||||
"implementation": "controllers/StackedPlotController.js",
|
||||
"depends": [ "$scope" ]
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"key": "telemetry.plot.overlay",
|
||||
"name": "Overlay Plot",
|
||||
"glyph": "t",
|
||||
"description": "A plot containing one or more telemetry elements.",
|
||||
"delegates": ["telemetry"],
|
||||
"features": "creation",
|
||||
"contains": [{"has": "telemetry"}],
|
||||
"model": {"composition": []},
|
||||
"properties": []
|
||||
},
|
||||
{
|
||||
"key": "telemetry.plot.stacked",
|
||||
"name": "Stacked Plot",
|
||||
"glyph": "t",
|
||||
"description": "A stacked plot of overlay plots.",
|
||||
"delegates": ["delegation"],
|
||||
"features": "creation",
|
||||
"contains": ["telemetry.plot.overlay", {"has": "telemetry"}],
|
||||
"model": {"composition": []},
|
||||
"properties": []
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "colorService",
|
||||
"implementation": "services/ColorService.js",
|
||||
"description": "Provides objects for working with colors."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
78
platform/features/plot-reborn/res/templates/mct-plot.html
Normal file
78
platform/features/plot-reborn/res/templates/mct-plot.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!--TODO: Don't require plotcontroller here. -->
|
||||
<div class="gl-plot">
|
||||
<div class="gl-plot-legend">
|
||||
<span class="plot-legend-item"
|
||||
ng-repeat="series in series track by $index">
|
||||
<span class="plot-color-swatch"
|
||||
ng-style="{ 'background-color': series.color.asHexString() }">
|
||||
</span>
|
||||
<span class="title-label">{{ series.name }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-coords"
|
||||
ng-if="mouseCoordinates">
|
||||
{{ displayableDomain(mouseCoordinates.positionAsPlotPoint.domain) }},
|
||||
{{ displayableRange(mouseCoordinates.positionAsPlotPoint.range) }}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-axis-area gl-plot-y">
|
||||
|
||||
<div class="gl-plot-label gl-plot-y-label">
|
||||
{{ axes.range.label}}
|
||||
</div>
|
||||
|
||||
<div ng-repeat="tick in axes.range.ticks track by $index"
|
||||
class="gl-plot-tick gl-plot-y-tick-label"
|
||||
ng-style="{ top: (100 * $index / (axes.range.ticks.length - 1)) + '%' }"
|
||||
style="margin-top: -0.50em;">
|
||||
{{ displayableRange(tick) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-display-area">
|
||||
|
||||
<div class="gl-plot-hash hash-v"
|
||||
ng-repeat="tick in axes.domain.ticks track by $index"
|
||||
ng-style="{ left: (100 * $index / (axes.domain.ticks.length - 1)) + '%', height: '100%' }"
|
||||
ng-show="$index > 0 && $index < (axes.domain.ticks.length - 1)">
|
||||
<!--TODO: Show/hide using CSS? -->
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-hash hash-h"
|
||||
ng-repeat="tick in axes.range.ticks track by $index"
|
||||
ng-style="{ bottom: (100 * $index / (axes.range.ticks.length - 1)) + '%', width: '100%' }"
|
||||
ng-show="$index > 0 && $index < (axes.range.ticks.length - 1)">
|
||||
<!--TODO: Show/hide using CSS? -->
|
||||
</div>
|
||||
|
||||
<!-- APPLY MCTPinch here-->
|
||||
<mct-chart series="series"
|
||||
viewport="viewport"
|
||||
rectangles="rectangles"
|
||||
ng-mousemove="plot.trackMousePosition($event)"
|
||||
ng-mouseleave="plot.untrackMousePosition()"
|
||||
ng-mousedown="plot.startMarquee()"
|
||||
ng-mouseup="plot.endMarquee()"
|
||||
mct-pinch>
|
||||
</mct-chart>
|
||||
|
||||
<span class="t-wait-spinner loading" ng-show="plot.isRequestPending()">
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-axis-area gl-plot-x">
|
||||
<div ng-repeat="tick in axes.domain.ticks track by $index"
|
||||
class="gl-plot-tick gl-plot-x-tick-label"
|
||||
ng-show="$index > 0 && $index < (axes.domain.ticks.length - 1)"
|
||||
ng-style="{ left: (100 * $index / (axes.domain.ticks.length - 1)) + '%' }">
|
||||
{{ displayableDomain(tick) }}
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-label gl-plot-x-label">
|
||||
{{ axes.domain.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
9
platform/features/plot-reborn/res/templates/plot.html
Normal file
9
platform/features/plot-reborn/res/templates/plot.html
Normal file
@ -0,0 +1,9 @@
|
||||
<span ng-controller="PlotController as controller">
|
||||
<mct-plot series="series"
|
||||
viewport="viewport"
|
||||
rectangles="rectangles"
|
||||
axes="axes"
|
||||
displayable-range="displayableRange"
|
||||
displayable-domain="displayableDomain">
|
||||
</mct-plot>
|
||||
</span>
|
@ -0,0 +1,8 @@
|
||||
<span ng-controller="StackedPlotController as stackedPlot">
|
||||
<div class="gl-plot"
|
||||
ng-style="{ height: 100 / telemetryObjects.length + '%'}"
|
||||
ng-repeat="telemetryObject in telemetryObjects">
|
||||
|
||||
<mct-overlay-plot domain-object="telemetryObject"></mct-overlay-plot>
|
||||
</div>
|
||||
</span>
|
239
platform/features/plot-reborn/src/controllers/PlotController.js
Normal file
239
platform/features/plot-reborn/src/controllers/PlotController.js
Normal file
@ -0,0 +1,239 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
// TODO: Store this in more accessible locations / retrieve from
|
||||
// domainObject metadata.
|
||||
var DOMAIN_INTERVAL = 2 * 60 * 1000; // Two minutes.
|
||||
|
||||
function PlotController($scope, colorService, agentService) {
|
||||
var plotHistory = [],
|
||||
isLive = true,
|
||||
maxDomain = +new Date(),
|
||||
subscriptions = [],
|
||||
palette = new colorService.ColorPalette();
|
||||
|
||||
|
||||
function setToDefaultViewport() {
|
||||
// TODO: We shouldn't set the viewport until we have received data or something has given us a reasonable viewport.
|
||||
$scope.viewport = {
|
||||
topLeft: {
|
||||
domain: maxDomain - DOMAIN_INTERVAL,
|
||||
range: 1
|
||||
},
|
||||
bottomRight: {
|
||||
domain: maxDomain,
|
||||
range: -1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
setToDefaultViewport();
|
||||
|
||||
$scope.displayableRange = function (rangeValue) {
|
||||
// TODO: Call format function provided by domain object.
|
||||
return rangeValue;
|
||||
};
|
||||
$scope.displayableDomain = function (domainValue) {
|
||||
// TODO: Call format function provided by domain object.
|
||||
return new Date(domainValue).toUTCString();
|
||||
};
|
||||
|
||||
$scope.series = [];
|
||||
|
||||
$scope.rectangles = [];
|
||||
|
||||
function updateSeriesFromTelemetry(series, seriesIndex, telemetry) {
|
||||
var domainValue = telemetry.getDomainValue(
|
||||
telemetry.getPointCount() - 1
|
||||
),
|
||||
rangeValue = telemetry.getRangeValue(
|
||||
telemetry.getPointCount() - 1
|
||||
),
|
||||
newTelemetry;
|
||||
// Track the biggest domain we've seen for sticky-ness.
|
||||
maxDomain = Math.max(maxDomain, domainValue);
|
||||
|
||||
newTelemetry = {
|
||||
domain: domainValue,
|
||||
range: rangeValue
|
||||
};
|
||||
series.data.push(newTelemetry);
|
||||
$scope.$broadcast('series:data:add', seriesIndex, [newTelemetry]);
|
||||
}
|
||||
|
||||
function subscribeToDomainObject(domainObject) {
|
||||
var telemetryCapability = domainObject.getCapability('telemetry'),
|
||||
model = domainObject.getModel(),
|
||||
series,
|
||||
seriesIndex,
|
||||
updater;
|
||||
|
||||
series = {
|
||||
name: model.name,
|
||||
// TODO: Bring back PlotPalette.
|
||||
color: palette.getColor($scope.series.length),
|
||||
data: []
|
||||
};
|
||||
|
||||
$scope.series.push(series);
|
||||
seriesIndex = $scope.series.indexOf(series);
|
||||
|
||||
updater = updateSeriesFromTelemetry.bind(
|
||||
null,
|
||||
series,
|
||||
seriesIndex
|
||||
);
|
||||
subscriptions.push(telemetryCapability.subscribe(updater));
|
||||
}
|
||||
|
||||
function unlinkDomainObject() {
|
||||
subscriptions.forEach(function(subscription) {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
subscriptions = [];
|
||||
}
|
||||
|
||||
|
||||
function linkDomainObject(domainObject) {
|
||||
unlinkDomainObject();
|
||||
if (domainObject.hasCapability('telemetry')) {
|
||||
subscribeToDomainObject(domainObject);
|
||||
} else if (domainObject.hasCapability('delegation')) {
|
||||
// Makes no sense that we have to use a subscription to get domain objects associated with delegates (and their names). We can map the same series generation code to telemetry delegates; Let's do that ourselves.
|
||||
var subscribeToDelegates = function(delegates) {
|
||||
return delegates.forEach(subscribeToDomainObject);
|
||||
// TODO: Should return a promise.
|
||||
};
|
||||
domainObject
|
||||
.getCapability('delegation')
|
||||
.getDelegates('telemetry')
|
||||
.then(subscribeToDelegates);
|
||||
// TODO: should have a catch.
|
||||
} else {
|
||||
throw new Error('Domain object type not supported.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onUserViewportChangeStart() {
|
||||
// TODO: this is a great time to track a history entry.
|
||||
// Disable live mode so they have full control of viewport.
|
||||
plotHistory.push($scope.viewport);
|
||||
|
||||
isLive = false;
|
||||
$scope.axes.domain.label = "Time (Manipulated)";
|
||||
}
|
||||
|
||||
// Returns the value of the left domain value
|
||||
// used when the right value has been adjusted and
|
||||
// a pan or zoom has occurred
|
||||
function getLeftInterval(intervalTL, intervalBR) {
|
||||
return intervalTL.domain + (maxDomain - intervalBR.domain);
|
||||
}
|
||||
|
||||
// Checks if the user is on mobile or desktop,
|
||||
// based on that returns the boolean value
|
||||
// if the chart should be snapped to the right
|
||||
// side of the screen
|
||||
function getSnapCheck(viewport, onMobile) {
|
||||
// Default amount within which to snap
|
||||
// for desktop version
|
||||
var snapPercent = 10;
|
||||
|
||||
if(onMobile) {
|
||||
// Smaller amount within which to snap
|
||||
// for mobile version
|
||||
snapPercent = 75;
|
||||
}
|
||||
|
||||
return (Math.abs(maxDomain - viewport.bottomRight.domain) < (DOMAIN_INTERVAL/snapPercent));
|
||||
}
|
||||
|
||||
// Spans the chart to the right domain value to update the
|
||||
// chart live and keep up with the maxDomain
|
||||
function snapToRight() {
|
||||
|
||||
// Sets the chart to being live and changes the
|
||||
// range name to show that the chart is updating
|
||||
isLive = true;
|
||||
$scope.axes.domain.label = "Time (Updating Live)";
|
||||
|
||||
// Changes right domain value to maxDomain (value
|
||||
// of latest chart domain value)
|
||||
$scope.viewport.bottomRight.domain = maxDomain;
|
||||
|
||||
// Adjusts the left domain value to keep up with the
|
||||
// right domain change by adding it to the current left domain
|
||||
$scope.viewport.topLeft.domain = getLeftInterval($scope.viewport.topLeft,
|
||||
$scope.viewport.bottomRight);
|
||||
}
|
||||
|
||||
// In the past what has happened is that the interval between the left and right domain
|
||||
// is set to 2 minutes all the time. And the range is -1 and 1 on update
|
||||
function onUserViewportChangeEnd(event, viewport) {
|
||||
// If the new viewport is "close enough" to the maxDomain then
|
||||
// enable live mode. Set empirically to 10% of the domain
|
||||
// interval.
|
||||
// TODO: Better UX pattern for this.
|
||||
|
||||
// Checks if the chart needs to snap to the right based on the
|
||||
// current device and where the right domain is located
|
||||
if (getSnapCheck(viewport, agentService.isMobile(navigator.userAgent))) {
|
||||
snapToRight();
|
||||
} else {
|
||||
|
||||
// The viewport has been changed, but is not actively
|
||||
// keeping up with the plot, therefore isLive = false
|
||||
isLive = false;
|
||||
$scope.axes.domain.label = "Time (Manipulated)";
|
||||
}
|
||||
plotHistory.push(viewport);
|
||||
}
|
||||
|
||||
function viewportForMaxDomain() {
|
||||
return {
|
||||
topLeft: {
|
||||
range: $scope.viewport.topLeft.range,
|
||||
domain: getLeftInterval($scope.viewport.topLeft,
|
||||
$scope.viewport.bottomRight)
|
||||
},
|
||||
bottomRight: {
|
||||
range: $scope.viewport.bottomRight.range,
|
||||
domain: maxDomain
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function followDataIfLive() {
|
||||
if (isLive) {
|
||||
$scope.viewport = viewportForMaxDomain();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$on('series:data:add', followDataIfLive);
|
||||
$scope.$on('user:viewport:change:end', onUserViewportChangeEnd);
|
||||
$scope.$on('user:viewport:change:start', onUserViewportChangeStart);
|
||||
|
||||
$scope.$watch('domainObject', linkDomainObject);
|
||||
|
||||
return {
|
||||
historyBack: function() {
|
||||
// TODO: Step History Back.
|
||||
},
|
||||
historyForward: function() {
|
||||
// TODO: Step History Forward.
|
||||
},
|
||||
resetZoom: function() {
|
||||
// TODO: Reset view to defaults. Keep history stack alive?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return PlotController;
|
||||
|
||||
}
|
||||
);
|
@ -0,0 +1,38 @@
|
||||
/*global define */
|
||||
|
||||
define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
function StackedPlotController($scope) {
|
||||
|
||||
$scope.telemetryObjects = [];
|
||||
|
||||
var linkDomainObject = function(domainObject) {
|
||||
$scope.telemetryObjects = [];
|
||||
if (domainObject.hasCapability('telemetry')) {
|
||||
$scope.telemetryObjects = [domainObject];
|
||||
} else if (domainObject.hasCapability('delegation')) {
|
||||
|
||||
var addObjectsIfCompatible = function(objects) {
|
||||
objects.forEach(function(object) {
|
||||
if (object.hasCapability('telemetry')) {
|
||||
$scope.telemetryObjects.push(object);
|
||||
} else if (object.hasCapability('delegation')) {
|
||||
$scope.telemetryObjects.push(object);
|
||||
}
|
||||
});
|
||||
};
|
||||
domainObject
|
||||
.useCapability('composition')
|
||||
.then(addObjectsIfCompatible);
|
||||
// TODO: should have a catch.
|
||||
} else {
|
||||
throw new Error('Domain object type not supported.');
|
||||
}
|
||||
};
|
||||
$scope.$watch('domainObject', linkDomainObject);
|
||||
}
|
||||
return StackedPlotController;
|
||||
}
|
||||
);
|
239
platform/features/plot-reborn/src/directives/MCTChart.js
Normal file
239
platform/features/plot-reborn/src/directives/MCTChart.js
Normal file
@ -0,0 +1,239 @@
|
||||
/*global define,requestAnimationFrame,Float32Array*/
|
||||
|
||||
/**
|
||||
* Module defining MCTChart. Created by vwoeltje on 11/12/14.
|
||||
*/
|
||||
define(
|
||||
["../draw/DrawLoader"],
|
||||
function (DrawLoader) {
|
||||
"use strict";
|
||||
|
||||
var TEMPLATE = "<canvas style='position: absolute; background: none; width: 100%; height: 100%;'></canvas>";
|
||||
|
||||
/**
|
||||
* Offsetter adjusts domain and range values by a fixed amount,
|
||||
* generally increasing the precision of the 32 bit float representation
|
||||
* required for plotting.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Offsetter(domainOffset, rangeOffset) {
|
||||
this.domainOffset = domainOffset;
|
||||
this.rangeOffset = rangeOffset;
|
||||
}
|
||||
|
||||
Offsetter.prototype.domain = function(dataDomain) {
|
||||
return dataDomain - this.domainOffset;
|
||||
};
|
||||
|
||||
Offsetter.prototype.range = function(dataRange) {
|
||||
return dataRange - this.rangeOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* MCTChart draws charts utilizing a drawAPI.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MCTChart($interval, agentService) {
|
||||
|
||||
function linkChart($scope, $element) {
|
||||
var canvas = $element.find("canvas")[0],
|
||||
isDestroyed = false,
|
||||
activeInterval,
|
||||
drawAPI,
|
||||
lines = [],
|
||||
offset;
|
||||
|
||||
drawAPI = DrawLoader.getDrawAPI(canvas);
|
||||
|
||||
if (!drawAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
function createOffset() {
|
||||
if (offset) {
|
||||
return;
|
||||
}
|
||||
if (!$scope.viewport ||
|
||||
!$scope.viewport.topLeft ||
|
||||
!$scope.viewport.bottomRight) {
|
||||
return;
|
||||
}
|
||||
offset = new Offsetter(
|
||||
$scope.viewport.topLeft.domain,
|
||||
$scope.viewport.topLeft.range
|
||||
);
|
||||
}
|
||||
|
||||
function lineFromSeries(series) {
|
||||
// TODO: handle when lines get longer than 10,000 points.
|
||||
// Each line allocates 10,000 points. This should be more
|
||||
// that we ever need, but we have to decide how to handle
|
||||
// this at the higher level. I imagine the plot controller
|
||||
// should watch it's series and when they get huge, slice
|
||||
// them in half and delete the oldest half.
|
||||
//
|
||||
// As long as the controller replaces $scope.series with a
|
||||
// new series object, then this directive will
|
||||
// automatically generate new arrays for those lines.
|
||||
// In practice, the overhead of regenerating these lines
|
||||
// appears minimal.
|
||||
var lineBuffer = new Float32Array(20000),
|
||||
i = 0;
|
||||
for (i = 0; i < series.data.length; i++) {
|
||||
lineBuffer[2*i] = offset.domain(series.data[i].domain);
|
||||
lineBuffer[2*i+1] = offset.range(series.data[i].range);
|
||||
}
|
||||
return {
|
||||
color: series.color,
|
||||
buffer: lineBuffer,
|
||||
pointCount: series.data.length
|
||||
};
|
||||
}
|
||||
|
||||
function drawSeries() {
|
||||
// TODO: Don't regenerate lines on each frame.
|
||||
if (!$scope.series || !$scope.series.length) {
|
||||
return;
|
||||
}
|
||||
lines = $scope.series.map(lineFromSeries);
|
||||
lines.forEach(function(line) {
|
||||
drawAPI.drawLine(
|
||||
line.buffer,
|
||||
line.color.asRGBAArray(),
|
||||
line.pointCount
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function drawRectangles() {
|
||||
if ($scope.rectangles) {
|
||||
$scope.rectangles.forEach(function(rect) {
|
||||
drawAPI.drawSquare(
|
||||
[
|
||||
offset.domain(rect.start.domain),
|
||||
offset.range(rect.start.range)
|
||||
],
|
||||
[
|
||||
offset.domain(rect.end.domain),
|
||||
offset.range(rect.end.range)
|
||||
],
|
||||
rect.color
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateViewport() {
|
||||
var dimensions,
|
||||
origin;
|
||||
|
||||
dimensions = [
|
||||
Math.abs(
|
||||
offset.domain($scope.viewport.topLeft.domain) -
|
||||
offset.domain($scope.viewport.bottomRight.domain)
|
||||
),
|
||||
Math.abs(
|
||||
offset.range($scope.viewport.topLeft.range) -
|
||||
offset.range($scope.viewport.bottomRight.range)
|
||||
)
|
||||
];
|
||||
|
||||
origin = [
|
||||
offset.domain(
|
||||
$scope.viewport.topLeft.domain
|
||||
),
|
||||
offset.range(
|
||||
$scope.viewport.bottomRight.range
|
||||
)
|
||||
];
|
||||
|
||||
drawAPI.setDimensions(
|
||||
dimensions,
|
||||
origin
|
||||
);
|
||||
}
|
||||
|
||||
function onSeriesDataAdd(event, seriesIndex, points) {
|
||||
var line = lines[seriesIndex];
|
||||
points.forEach(function (point) {
|
||||
line.buffer[2*line.pointCount] = offset.domain(point.domain);
|
||||
line.buffer[2*line.pointCount+1] = offset.range(point.range);
|
||||
line.pointCount += 1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function redraw() {
|
||||
if (isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestAnimationFrame(redraw);
|
||||
canvas.width = canvas.offsetWidth;
|
||||
canvas.height = canvas.offsetHeight;
|
||||
drawAPI.clear();
|
||||
createOffset();
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
updateViewport();
|
||||
drawSeries();
|
||||
drawRectangles();
|
||||
}
|
||||
|
||||
|
||||
function drawIfResized() {
|
||||
if (canvas.width !== canvas.offsetWidth ||
|
||||
canvas.height !== canvas.offsetHeight) {
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
function destroyChart() {
|
||||
isDestroyed = true;
|
||||
if (activeInterval) {
|
||||
$interval.cancel(activeInterval);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for resize, on a timer, the timer is 15
|
||||
// on mobile (to allow quick refresh of drawing).
|
||||
if(agentService.isMobile(navigator.userAgent)) {
|
||||
activeInterval = $interval(drawIfResized, 15, false);
|
||||
} else {
|
||||
activeInterval = $interval(drawIfResized, 1000, false);
|
||||
}
|
||||
|
||||
$scope.$on('series:data:add', onSeriesDataAdd);
|
||||
redraw();
|
||||
|
||||
// Stop checking for resize when $scope is destroyed
|
||||
$scope.$on("$destroy", destroyChart);
|
||||
}
|
||||
|
||||
return {
|
||||
// Apply directive only to $elements
|
||||
restrict: "E",
|
||||
|
||||
// Template to use (a canvas $element)
|
||||
template: TEMPLATE,
|
||||
|
||||
// Link function; set up $scope
|
||||
link: linkChart,
|
||||
|
||||
// Initial, isolate $scope for the directive
|
||||
scope: {
|
||||
draw: "=" ,
|
||||
rectangles: "=",
|
||||
series: "=",
|
||||
viewport: "="
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return MCTChart;
|
||||
}
|
||||
);
|
@ -0,0 +1,14 @@
|
||||
/*global define*/
|
||||
|
||||
define(function () {
|
||||
return function MCTOverlayPlot() {
|
||||
return {
|
||||
restrict: "E",
|
||||
templateUrl: 'platform/features/plot-reborn/res/templates/plot.html',
|
||||
scope: {
|
||||
domainObject: "="
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
244
platform/features/plot-reborn/src/directives/MCTPinch.js
Normal file
244
platform/features/plot-reborn/src/directives/MCTPinch.js
Normal file
@ -0,0 +1,244 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
function MCTPinch(agentService) {
|
||||
|
||||
/*
|
||||
* Links the attributes with the
|
||||
* provided link function and nested
|
||||
* touch event functions
|
||||
*/
|
||||
function link($scope, element) {
|
||||
|
||||
// isPan and isPinch variables are set after the start
|
||||
// of a gestures and is checked over the change of that
|
||||
// gesture. These are used to differentiate gestures and
|
||||
// force only one type of gesture to be done at a time
|
||||
var isPan = false,
|
||||
isPinch = false;
|
||||
|
||||
// Returns position of touch event
|
||||
function trackPosition(event) {
|
||||
return {
|
||||
clientX: event.clientX,
|
||||
clientY: event.clientY
|
||||
};
|
||||
}
|
||||
|
||||
// Calculates the midpoint between two given
|
||||
// coordinates and returns it as coordinate object
|
||||
function calculateMidpoint(coordOne, coordTwo) {
|
||||
return {
|
||||
clientX: (coordOne.clientX + coordTwo.clientX) / 2,
|
||||
clientY: (coordOne.clientY + coordTwo.clientY) / 2
|
||||
};
|
||||
}
|
||||
|
||||
// Calculates the distance between two coordinates
|
||||
// and returns as number/integer value
|
||||
function calculateDistance(coordOne, coordTwo) {
|
||||
return Math.sqrt(Math.pow(coordOne.clientX - coordTwo.clientX, 2) +
|
||||
Math.pow(coordOne.clientY - coordTwo.clientY, 2));
|
||||
}
|
||||
|
||||
// Checks if the user is going to pan by checking the number
|
||||
// of touches on the screen (one touch means pan)
|
||||
function checkPan(event) {
|
||||
return (event.changedTouches.length === 1) ||
|
||||
(event.touches.length === 1);
|
||||
}
|
||||
|
||||
// Checks if the user is going to pinch by checking the number
|
||||
// of touches on the screen (two touches means pinch)
|
||||
function checkPinch(event) {
|
||||
return (event.changedTouches.length === 2) ||
|
||||
(event.touches.length === 2);
|
||||
}
|
||||
|
||||
// On touch start the 'touch' is tracked and
|
||||
// the event is emitted through scope
|
||||
function touchStart(event) {
|
||||
var touchPosition;
|
||||
|
||||
// If two touches or change touches are occurring
|
||||
// than user is doing a pinch gesture
|
||||
if (checkPinch(event)) {
|
||||
|
||||
// User has started pinch, sets isPinch and resets isPan
|
||||
isPan = false;
|
||||
isPinch = true;
|
||||
|
||||
// Position of both touches are tracked and saved in variable
|
||||
touchPosition = [trackPosition(event.touches[0]),
|
||||
trackPosition(event.touches[1])];
|
||||
|
||||
// Emits the start of the pinch and passes the
|
||||
// touch coordinates (touches), the bounds of the
|
||||
// event, the midpoint of both touch coorddinates,
|
||||
// and the distance between the two touch coordinates
|
||||
$scope.$emit('mct:pinch:start', {
|
||||
touches: touchPosition,
|
||||
bounds: event.target.getBoundingClientRect(),
|
||||
midpoint: calculateMidpoint(touchPosition[0], touchPosition[1]),
|
||||
distance: calculateDistance(touchPosition[0], touchPosition[1])
|
||||
});
|
||||
|
||||
// Stops other gestures/button clicks from being active
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
// If one touch or change touch is occurring
|
||||
// user is doing a single finger pan gesture
|
||||
else if (checkPan(event)) {
|
||||
|
||||
// User has started pan, sets isPan and resets isPinch
|
||||
isPinch = false;
|
||||
isPan = true;
|
||||
|
||||
// Position of single touch is tracked and
|
||||
// saved in variable
|
||||
touchPosition = trackPosition(event.touches[0]);
|
||||
|
||||
// Emits the start of the pan and passes the
|
||||
// touch coordinates (touch), and the bounds
|
||||
// of the event
|
||||
$scope.$emit('mct:pan:start', {
|
||||
touch: touchPosition,
|
||||
bounds: event.target.getBoundingClientRect()
|
||||
});
|
||||
|
||||
// Stops other gestures/button clicks from being active
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// As the touch move occurs, the touches are tracked and
|
||||
// the event is emitted through scope
|
||||
function touchChange(event) {
|
||||
var touchPosition;
|
||||
|
||||
// If two touches or change touches are occurring
|
||||
// and the user has started a pinch than user is
|
||||
// doing a pinch gesture
|
||||
if (checkPinch(event) && isPinch) {
|
||||
|
||||
// Position of both touches are tracked and saved in variable. If change
|
||||
// in touch of either coordinate is undefined, uses touch instead
|
||||
touchPosition = [trackPosition(event.changedTouches[0] || event.touches[0]),
|
||||
trackPosition(event.changedTouches[1] || event.touches[1])];
|
||||
|
||||
// Emits the change in pinch and passes the
|
||||
// touch coordinates (touches), the bounds of the
|
||||
// event, the midpoint of both touch coorddinates,
|
||||
// and the distance between the two touch coordinates
|
||||
$scope.$emit('mct:pinch:change', {
|
||||
touches: touchPosition,
|
||||
bounds: event.target.getBoundingClientRect(),
|
||||
midpoint: calculateMidpoint(touchPosition[0], touchPosition[1]),
|
||||
distance: calculateDistance(touchPosition[0], touchPosition[1])
|
||||
});
|
||||
|
||||
// Stops other gestures/button clicks from being active
|
||||
event.preventDefault();
|
||||
}
|
||||
// If one touch or change touch is occurring
|
||||
// user is doing a single finger pan gesture
|
||||
else if (checkPan(event) && isPan) {
|
||||
|
||||
// Position of single changed touch or touch is tracked and saved in variable
|
||||
touchPosition = trackPosition(event.changedTouches[0] || event.touches[0]);
|
||||
|
||||
// Emits the change of the pan and passes the
|
||||
// touch coordinates (touch), and the bounds
|
||||
// of the event
|
||||
$scope.$emit('mct:pan:change', {
|
||||
touch: touchPosition,
|
||||
bounds: event.target.getBoundingClientRect()
|
||||
});
|
||||
|
||||
// Stops other gestures/button clicks from being active
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// On the 'touchend' or 'touchcancel' the event
|
||||
// is emitted through scope
|
||||
function touchEnd(event) {
|
||||
|
||||
// Emits that this is the end of the touch
|
||||
$scope.$emit('mct:ptouch:end');
|
||||
|
||||
// set pan/pinch statuses to false
|
||||
// when the user stops touching the screen
|
||||
isPan = false;
|
||||
isPinch = false;
|
||||
|
||||
// Stops other gestures/button clicks from being active
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// On Mobile, checks for touch start, move, and end/cancel
|
||||
if (agentService.isMobile(navigator.userAgent)) {
|
||||
element.on('touchstart', touchStart);
|
||||
element.on('touchmove', touchChange);
|
||||
element.on('touchend', touchEnd);
|
||||
element.on('touchcancel', touchEnd);
|
||||
}
|
||||
|
||||
// Stop checking for touch when scope is destroyed
|
||||
// (when user navigates away from graph).
|
||||
$scope.$on("$destroy", function () {
|
||||
|
||||
// All elements' event listeners are
|
||||
// removed
|
||||
element.off('touchstart', touchStart);
|
||||
element.off('touchmove', touchChange);
|
||||
element.off('touchend', touchEnd);
|
||||
element.off('touchcancel', touchEnd);
|
||||
|
||||
// If for some reason, midtouch the
|
||||
// user is navigated away, set pan/pinch
|
||||
// statuses to false
|
||||
isPan = false;
|
||||
isPinch = false;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
// MCTPinch is treated as an attribute
|
||||
restrict: "A",
|
||||
|
||||
// Link with the provided function above
|
||||
link: link
|
||||
};
|
||||
}
|
||||
|
||||
return MCTPinch;
|
||||
|
||||
}
|
||||
);
|
465
platform/features/plot-reborn/src/directives/MCTPlot.js
Normal file
465
platform/features/plot-reborn/src/directives/MCTPlot.js
Normal file
@ -0,0 +1,465 @@
|
||||
/*global define,window*/
|
||||
|
||||
define(
|
||||
[
|
||||
'../lib/utils'
|
||||
],
|
||||
function (utils) {
|
||||
"use strict";
|
||||
|
||||
var RANGE_TICK_COUNT = 7,
|
||||
DOMAIN_TICK_COUNT = 5,
|
||||
ZOOM_AMT = 0.02,
|
||||
PINCH_DRAG_AMT = 3;
|
||||
|
||||
function MCTPlot() {
|
||||
|
||||
function link($scope, $element) {
|
||||
// Now that we're here, let's handle some scope management that the controller would otherwise handle.
|
||||
|
||||
if (typeof $scope.rectangles === "undefined") {
|
||||
$scope.rectangles = [];
|
||||
}
|
||||
if (typeof $scope.displayableRange === "undefined") {
|
||||
$scope.displayableRange = function (x) { return x; };
|
||||
}
|
||||
if (typeof $scope.displayableDomain === "undefined") {
|
||||
$scope.displayableDomain = function (x) { return x; };
|
||||
}
|
||||
if (typeof $scope.axes === "undefined") {
|
||||
$scope.axes = {
|
||||
domain: {
|
||||
label: "Time (Updating Live)",
|
||||
tickCount: DOMAIN_TICK_COUNT,
|
||||
ticks: []
|
||||
},
|
||||
range: {
|
||||
label: "Value",
|
||||
tickCount: RANGE_TICK_COUNT,
|
||||
ticks: []
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var dragStart,
|
||||
marqueeBox = {},
|
||||
marqueeRect, // Set when exists.
|
||||
chartElementBounds,
|
||||
firstTouch,
|
||||
firstTouchDistance,
|
||||
prevTouchDistance,
|
||||
$canvas = $element.find('canvas');
|
||||
|
||||
function updateAxesForCurrentViewport() {
|
||||
// Update axes definitions for current viewport.
|
||||
['domain', 'range'].forEach(function (axisName) {
|
||||
var axis = $scope.axes[axisName],
|
||||
firstTick = $scope.viewport.topLeft[axisName],
|
||||
lastTick = $scope.viewport.bottomRight[axisName],
|
||||
axisSize = firstTick - lastTick,
|
||||
denominator = axis.tickCount - 1,
|
||||
tickNumber,
|
||||
tickIncrement,
|
||||
tickValue;
|
||||
// Yes, ticksize is negative for domain and positive for range.
|
||||
// It's because ticks are generated/displayed top to bottom and left to right.
|
||||
axis.ticks = [];
|
||||
for (tickNumber = 0; tickNumber < axis.tickCount; tickNumber = tickNumber + 1) {
|
||||
tickIncrement = (axisSize * (tickNumber / denominator));
|
||||
tickValue = firstTick - tickIncrement;
|
||||
axis.ticks.push(
|
||||
tickValue
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function drawMarquee() {
|
||||
// Create rectangle for Marquee if it should be set.
|
||||
if (marqueeBox && marqueeBox.start && marqueeBox.end) {
|
||||
if (!marqueeRect) {
|
||||
marqueeRect = {};
|
||||
$scope.rectangles.push(marqueeRect);
|
||||
}
|
||||
marqueeRect.start = marqueeBox.start;
|
||||
marqueeRect.end = marqueeBox.end;
|
||||
marqueeRect.color = [1, 1, 1, 0.5];
|
||||
marqueeRect.layer = 'top'; // TODO: implement this.
|
||||
$scope.$broadcast('rectangle-change');
|
||||
} else if (marqueeRect && $scope.rectangles.indexOf(marqueeRect) !== -1) {
|
||||
$scope.rectangles.splice($scope.rectangles.indexOf(marqueeRect));
|
||||
marqueeRect = undefined;
|
||||
$scope.$broadcast('rectangle-change');
|
||||
}
|
||||
}
|
||||
|
||||
function untrackMousePosition() {
|
||||
$scope.mouseCoordinates = undefined;
|
||||
}
|
||||
function updateMarquee() {
|
||||
// Update the marquee box in progress.
|
||||
marqueeBox.end = $scope.mouseCoordinates.positionAsPlotPoint;
|
||||
drawMarquee();
|
||||
}
|
||||
function startMarquee() {
|
||||
marqueeBox.start = $scope.mouseCoordinates.positionAsPlotPoint;
|
||||
}
|
||||
function endMarquee() {
|
||||
// marqueeBox start/end are opposite corners but we need
|
||||
// topLeft and bottomRight.
|
||||
var boxPoints = utils.boxPointsFromOppositeCorners(marqueeBox.start, marqueeBox.end),
|
||||
newViewport = utils.oppositeCornersFromBoxPoints(boxPoints);
|
||||
|
||||
marqueeBox = {};
|
||||
drawMarquee();
|
||||
$scope.$emit('user:viewport:change:end', newViewport);
|
||||
$scope.viewport = newViewport;
|
||||
}
|
||||
|
||||
function startDrag($event) {
|
||||
$scope.$emit('user:viewport:change:start');
|
||||
if (!$scope.mouseCoordinates) {
|
||||
return;
|
||||
}
|
||||
$event.preventDefault();
|
||||
// Track drag location relative to position over element
|
||||
// not domain, as chart viewport will change as we drag.
|
||||
dragStart = $scope.mouseCoordinates.positionAsPlotPoint;
|
||||
// Tell controller that we're starting to navigate.
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateDrag() {
|
||||
// calculate offset between points. Apply that offset to viewport.
|
||||
var newPosition = $scope.mouseCoordinates.positionAsPlotPoint,
|
||||
dDomain = dragStart.domain - newPosition.domain,
|
||||
dRange = dragStart.range - newPosition.range;
|
||||
|
||||
$scope.viewport = {
|
||||
topLeft: {
|
||||
domain: $scope.viewport.topLeft.domain + dDomain,
|
||||
range: $scope.viewport.topLeft.range + dRange
|
||||
},
|
||||
bottomRight: {
|
||||
domain: $scope.viewport.bottomRight.domain + dDomain,
|
||||
range: $scope.viewport.bottomRight.range + dRange
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function endDrag() {
|
||||
dragStart = undefined;
|
||||
$scope.$emit('user:viewport:change:end', $scope.viewport);
|
||||
}
|
||||
|
||||
// Similar to trackMousePosition, where the touch position is converted
|
||||
// into a plot point position and over element position using utils
|
||||
function trackTouchPosition(touchPosition, bounds) {
|
||||
var positionOverElement,
|
||||
positionAsPlotPoint,
|
||||
position;
|
||||
|
||||
chartElementBounds = bounds;
|
||||
|
||||
positionOverElement = {
|
||||
x: touchPosition.clientX - bounds.left,
|
||||
y: touchPosition.clientY - bounds.top
|
||||
};
|
||||
|
||||
positionAsPlotPoint = utils.elementPositionAsPlotPosition(
|
||||
positionOverElement,
|
||||
bounds,
|
||||
$scope.viewport
|
||||
);
|
||||
|
||||
position = {
|
||||
positionOverElement: positionOverElement,
|
||||
positionAsPlotPoint: positionAsPlotPoint
|
||||
};
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
function trackMousePosition($event) {
|
||||
// Calculate coordinates of mouse related to canvas and as
|
||||
// domain, range value and make available in scope for display.
|
||||
|
||||
var bounds = $event.target.getBoundingClientRect(),
|
||||
positionOverElement,
|
||||
positionAsPlotPoint;
|
||||
|
||||
chartElementBounds = bounds;
|
||||
|
||||
|
||||
positionOverElement = {
|
||||
x: $event.clientX - bounds.left,
|
||||
y: $event.clientY - bounds.top
|
||||
};
|
||||
|
||||
positionAsPlotPoint = utils.elementPositionAsPlotPosition(
|
||||
positionOverElement,
|
||||
bounds,
|
||||
$scope.viewport
|
||||
);
|
||||
|
||||
$scope.mouseCoordinates = {
|
||||
positionOverElement: positionOverElement,
|
||||
positionAsPlotPoint: positionAsPlotPoint
|
||||
};
|
||||
|
||||
if (marqueeBox && marqueeBox.start) {
|
||||
updateMarquee();
|
||||
}
|
||||
|
||||
if (dragStart) {
|
||||
updateDrag();
|
||||
}
|
||||
}
|
||||
|
||||
function watchForMarquee() {
|
||||
$canvas.removeClass('plot-drag');
|
||||
$canvas.addClass('plot-marquee');
|
||||
$canvas.on('mousedown', startMarquee);
|
||||
$canvas.on('mouseup', endMarquee);
|
||||
$canvas.off('mousedown', startDrag);
|
||||
$canvas.off('mouseup', endDrag);
|
||||
}
|
||||
|
||||
function watchForDrag() {
|
||||
$canvas.addClass('plot-drag');
|
||||
$canvas.removeClass('plot-marquee');
|
||||
$canvas.on('mousedown', startDrag);
|
||||
$canvas.on('mouseup', endDrag);
|
||||
$canvas.off('mousedown', startMarquee);
|
||||
$canvas.off('mouseup', endMarquee);
|
||||
}
|
||||
|
||||
function toggleInteractionMode(event) {
|
||||
if (event.keyCode === 16) { // shift key.
|
||||
watchForDrag();
|
||||
}
|
||||
}
|
||||
|
||||
function resetInteractionMode(event) {
|
||||
if (event.keyCode === 16) {
|
||||
watchForMarquee();
|
||||
}
|
||||
}
|
||||
|
||||
function stopWatching() {
|
||||
$canvas.off('mousedown', startDrag);
|
||||
$canvas.off('mouseup', endDrag);
|
||||
$canvas.off('mousedown', startMarquee);
|
||||
$canvas.off('mouseup', endMarquee);
|
||||
window.removeEventListener('keydown', toggleInteractionMode);
|
||||
window.removeEventListener('keyup', resetInteractionMode);
|
||||
}
|
||||
|
||||
$canvas.on('mousemove', trackMousePosition);
|
||||
$canvas.on('mouseleave', untrackMousePosition);
|
||||
watchForMarquee();
|
||||
|
||||
window.addEventListener('keydown', toggleInteractionMode);
|
||||
window.addEventListener('keyup', resetInteractionMode);
|
||||
|
||||
function onViewportChange() {
|
||||
if ($scope.mouseCoordinates && chartElementBounds) {
|
||||
$scope.mouseCoordinates.positionAsPlotPoint =
|
||||
utils.elementPositionAsPlotPosition(
|
||||
$scope.mouseCoordinates.positionOverElement,
|
||||
chartElementBounds,
|
||||
$scope.viewport
|
||||
);
|
||||
}
|
||||
// TODO: Discuss whether marqueeBox start should be fixed to data or fixed to canvas element, especially when "isLive is true".
|
||||
updateAxesForCurrentViewport();
|
||||
}
|
||||
|
||||
// Updates viewport based on touch location and current event bounds
|
||||
function updatePan(touch, bounds) {
|
||||
|
||||
// Sets the panPosition plot point (relative to chart)
|
||||
// and calculates domain/range by subtracting first touch's
|
||||
// plot point and current touch's plot point
|
||||
var panPosition = trackTouchPosition(touch, bounds).positionAsPlotPoint,
|
||||
dDomain = firstTouch.domain - panPosition.domain,
|
||||
dRange = firstTouch.range - panPosition.range;
|
||||
|
||||
// Viewport is set to calculated delta domain/range
|
||||
$scope.viewport = {
|
||||
topLeft: {
|
||||
domain: (($scope.viewport.topLeft.domain) + dDomain),
|
||||
range: (($scope.viewport.topLeft.range) + dRange)
|
||||
},
|
||||
bottomRight: {
|
||||
domain: (($scope.viewport.bottomRight.domain) + dDomain),
|
||||
range: (($scope.viewport.bottomRight.range) + dRange)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Starts the pan by emitting that viewport will be changed
|
||||
// also sets the first touch variable
|
||||
function startPan(touch, bounds) {
|
||||
$scope.$emit('user:viewport:change:start');
|
||||
firstTouch = trackTouchPosition(touch, bounds).positionAsPlotPoint;
|
||||
}
|
||||
|
||||
// Receives the emit of single touch pan start
|
||||
function onPanStart(event, touch) {
|
||||
startPan(touch.touch, touch.bounds);
|
||||
}
|
||||
|
||||
// Receives the emit of single touch pan change
|
||||
function onPanChange(event, touch) {
|
||||
updatePan(touch.touch, touch.bounds);
|
||||
}
|
||||
|
||||
// Sets the dimensions of the midpoint's domain and range distance to the
|
||||
// top left and bottom right corners of the viewport. Used to zoom relative to
|
||||
// midpoint pinch gestures 2 touches.
|
||||
function setDimensions(midpoint) {
|
||||
return {
|
||||
tl: {
|
||||
domain: Math.abs(midpoint.domain - ($scope.viewport.topLeft.domain)),
|
||||
range: Math.abs(midpoint.range - ($scope.viewport.topLeft.range))
|
||||
},
|
||||
br: {
|
||||
domain: Math.abs(($scope.viewport.bottomRight.domain) - midpoint.domain),
|
||||
range: Math.abs(($scope.viewport.bottomRight.range) - midpoint.range)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Calculates the viewport for a zoom gesture
|
||||
function calculateViewport(midpoint, ratio) {
|
||||
|
||||
// Uses the distance ratio passed in and the
|
||||
// zoom amount (variable set at top) to find the
|
||||
// amount of zoom per change in pinch gesture and
|
||||
// whether it is zooming in or out
|
||||
var zoomTL, zoomBR,
|
||||
dimensions = setDimensions(midpoint),
|
||||
checkRatio = (ratio - 1) || 0,
|
||||
type = (-1 * (checkRatio / Math.abs(checkRatio))) || 1,
|
||||
zoomAmt = type * ZOOM_AMT;
|
||||
|
||||
// Sets the domain/range difference to applied to the
|
||||
// top left and bottom right plot points
|
||||
zoomTL = {
|
||||
domain: zoomAmt * dimensions.tl.domain,
|
||||
range: zoomAmt * dimensions.tl.range
|
||||
};
|
||||
zoomBR = {
|
||||
domain: zoomAmt * dimensions.br.domain,
|
||||
range: zoomAmt * dimensions.br.range
|
||||
};
|
||||
|
||||
// Applies and returns the changed for zoom top left and bottom right
|
||||
// plot points
|
||||
return {
|
||||
topLeft: {
|
||||
domain: (($scope.viewport.topLeft.domain) + zoomTL.domain),
|
||||
range: (($scope.viewport.topLeft.range) - zoomTL.range)
|
||||
},
|
||||
bottomRight: {
|
||||
domain: (($scope.viewport.bottomRight.domain) - zoomBR.domain),
|
||||
range: (($scope.viewport.bottomRight.range) + zoomBR.range)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Updates the viewport based on the amount of zooming (pinching) user is doing
|
||||
// Pinch inwards (zoom out): distanceRatio > 1
|
||||
// Pinch outwards (zoom in): distanceRatio < 1
|
||||
function updateZoom(midpoint, bounds, distance) {
|
||||
|
||||
// Gets the current midpoint and distance ratio to be used to
|
||||
// calculate new viewport
|
||||
var midpointPosition = trackTouchPosition(midpoint, bounds).positionAsPlotPoint,
|
||||
distanceRatio = ((prevTouchDistance || firstTouchDistance) / distance);
|
||||
|
||||
// Sets the new viewport
|
||||
$scope.viewport = calculateViewport(midpointPosition, distanceRatio);
|
||||
}
|
||||
|
||||
// Starts the zoom by emitting that viewport will be changed
|
||||
// also sets the first touch variable (midpoint) if panning will
|
||||
// happen and sets the distance between the first touches occurring
|
||||
function startZoom(midpoint, bounds, distance) {
|
||||
$scope.$emit('user:viewport:change:start');
|
||||
firstTouchDistance = distance;
|
||||
firstTouch = trackTouchPosition(midpoint, bounds).positionAsPlotPoint;
|
||||
}
|
||||
|
||||
// Receives the emit of the start of pinch touch
|
||||
function onPinchStart(event, touch) {
|
||||
startZoom(touch.midpoint, touch.bounds, touch.distance);
|
||||
}
|
||||
|
||||
function comparePinchDrag(distance, prevDistance) {
|
||||
return ((prevDistance + PINCH_DRAG_AMT) >= distance) &&
|
||||
((prevDistance - PINCH_DRAG_AMT) <= distance);
|
||||
}
|
||||
|
||||
// Receives the emit of the change of pinch touch,
|
||||
// differentiates between a pan and zoom
|
||||
function onPinchChange(event, touch) {
|
||||
|
||||
// Will pan if change in distance is within PINCH_DRAG_AMT
|
||||
// range relative to the previous distance
|
||||
if(comparePinchDrag(Math.round(touch.distance),
|
||||
Math.round(prevTouchDistance || firstTouchDistance))) {
|
||||
updatePan(touch.midpoint, touch.bounds);
|
||||
}
|
||||
// Will pinch in any other situation that the distance between
|
||||
// pinching touches is increasing or decreasing by more than
|
||||
// PINCH_DRAG_AMT
|
||||
else {
|
||||
updateZoom(touch.midpoint, touch.bounds, touch.distance);
|
||||
}
|
||||
|
||||
// Sets previous touch distance to current touch.distance (for next touch event)
|
||||
prevTouchDistance = touch.distance;
|
||||
}
|
||||
|
||||
// Receives emit for touch event ending and emits that the
|
||||
// viewport has stopped changing.
|
||||
function onTouchEnd() {
|
||||
$scope.$emit('user:viewport:change:end', $scope.viewport);
|
||||
}
|
||||
|
||||
// Receives the pinch to allow pinching/panning emitted by MCTPinch
|
||||
$scope.$on('mct:pinch:start', onPinchStart);
|
||||
$scope.$on('mct:pinch:change', onPinchChange);
|
||||
|
||||
// Receives the pan to allow panning emitted by MCTPinch
|
||||
$scope.$on('mct:pan:start', onPanStart);
|
||||
$scope.$on('mct:pan:change', onPanChange);
|
||||
|
||||
// Receives the end of the pan/pinch emitted by MCTPinch
|
||||
$scope.$on('mct:ptouch:end', onTouchEnd);
|
||||
|
||||
$scope.$on('$destroy', stopWatching);
|
||||
|
||||
$scope.$watchCollection('viewport', onViewportChange);
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: "E",
|
||||
templateUrl: 'platform/features/plot-reborn/res/templates/mct-plot.html',
|
||||
link: link,
|
||||
scope: {
|
||||
viewport: "=",
|
||||
series: "=",
|
||||
rectangles: "=?",
|
||||
axes: "=?",
|
||||
displayableRange: "=?",
|
||||
displayableDomain: "=?"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return MCTPlot;
|
||||
}
|
||||
);
|
120
platform/features/plot-reborn/src/draw/Draw2D.js
Normal file
120
platform/features/plot-reborn/src/draw/Draw2D.js
Normal file
@ -0,0 +1,120 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Create a new draw API utilizing the Canvas's 2D API for rendering.
|
||||
*
|
||||
* @constructor
|
||||
* @param {CanvasElement} canvas the canvas object to render upon
|
||||
* @throws {Error} an error is thrown if Canvas's 2D API is unavailable.
|
||||
*/
|
||||
function Draw2D(canvas) {
|
||||
var c2d = canvas.getContext('2d'),
|
||||
width = canvas.width,
|
||||
height = canvas.height,
|
||||
dimensions = [ width, height ],
|
||||
origin = [ 0, 0 ];
|
||||
|
||||
// Convert from logical to physical x coordinates
|
||||
function x(v) {
|
||||
return ((v - origin[0]) / dimensions[0]) * width;
|
||||
}
|
||||
|
||||
// Convert from logical to physical y coordinates
|
||||
function y(v) {
|
||||
return height - ((v - origin[1]) / dimensions[1]) * height;
|
||||
}
|
||||
|
||||
// Set the color to be used for drawing operations
|
||||
function setColor(color) {
|
||||
var mappedColor = color.map(function (c, i) {
|
||||
return i < 3 ? Math.floor(c * 255) : (c);
|
||||
}).join(',');
|
||||
c2d.strokeStyle = "rgba(" + mappedColor + ")";
|
||||
c2d.fillStyle = "rgba(" + mappedColor + ")";
|
||||
}
|
||||
|
||||
if (!c2d) {
|
||||
throw new Error("Canvas 2d API unavailable.");
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Clear the chart.
|
||||
*/
|
||||
clear: function () {
|
||||
width = canvas.width;
|
||||
height = canvas.height;
|
||||
c2d.clearRect(0, 0, width, height);
|
||||
},
|
||||
/**
|
||||
* Set the logical boundaries of the chart.
|
||||
* @param {number[]} dimensions the horizontal and
|
||||
* vertical dimensions of the chart
|
||||
* @param {number[]} origin the horizontal/vertical
|
||||
* origin of the chart
|
||||
*/
|
||||
setDimensions: function (newDimensions, newOrigin) {
|
||||
dimensions = newDimensions;
|
||||
origin = newOrigin;
|
||||
},
|
||||
/**
|
||||
* Draw the supplied buffer as a line strip (a sequence
|
||||
* of line segments), in the chosen color.
|
||||
* @param {Float32Array} buf the line strip to draw,
|
||||
* in alternating x/y positions
|
||||
* @param {number[]} color the color to use when drawing
|
||||
* the line, as an RGBA color where each element
|
||||
* is in the range of 0.0-1.0
|
||||
* @param {number} points the number of points to draw
|
||||
*/
|
||||
drawLine: function (buf, color, points) {
|
||||
var i;
|
||||
|
||||
setColor(color);
|
||||
|
||||
// Configure context to draw two-pixel-thick lines
|
||||
c2d.lineWidth = 2;
|
||||
|
||||
// Start a new path...
|
||||
if (buf.length > 1) {
|
||||
c2d.beginPath();
|
||||
c2d.moveTo(x(buf[0]), y(buf[1]));
|
||||
}
|
||||
|
||||
// ...and add points to it...
|
||||
for (i = 2; i < points * 2; i = i + 2) {
|
||||
c2d.lineTo(x(buf[i]), y(buf[i + 1]));
|
||||
}
|
||||
|
||||
// ...before finally drawing it.
|
||||
c2d.stroke();
|
||||
},
|
||||
/**
|
||||
* Draw a rectangle extending from one corner to another,
|
||||
* in the chosen color.
|
||||
* @param {number[]} min the first corner of the rectangle
|
||||
* @param {number[]} max the opposite corner
|
||||
* @param {number[]} color the color to use when drawing
|
||||
* the rectangle, as an RGBA color where each element
|
||||
* is in the range of 0.0-1.0
|
||||
*/
|
||||
drawSquare: function (min, max, color) {
|
||||
var x1 = x(min[0]),
|
||||
y1 = y(min[1]),
|
||||
w = x(max[0]) - x1,
|
||||
h = y(max[1]) - y1;
|
||||
|
||||
setColor(color);
|
||||
c2d.fillRect(x1, y1, w, h);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return Draw2D;
|
||||
}
|
||||
);
|
46
platform/features/plot-reborn/src/draw/DrawLoader.js
Normal file
46
platform/features/plot-reborn/src/draw/DrawLoader.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*global define,$log */
|
||||
|
||||
define(
|
||||
[
|
||||
'./DrawWebGL',
|
||||
'./Draw2D'
|
||||
],
|
||||
function ($log, DrawWebGL, Draw2D) {
|
||||
|
||||
var CHARTS = [
|
||||
DrawWebGL,
|
||||
Draw2D
|
||||
];
|
||||
|
||||
/**
|
||||
* Draw loader attaches a draw API to a canvas element and returns the
|
||||
* draw API.
|
||||
*/
|
||||
return {
|
||||
/**
|
||||
* Return the first draw API available. Returns
|
||||
* `undefined` if a draw API could not be constructed.
|
||||
*.
|
||||
* @param {CanvasElement} canvas - The canvas eelement to attach
|
||||
the draw API to.
|
||||
*/
|
||||
getDrawAPI: function (canvas) {
|
||||
var i;
|
||||
for (i = 0; i < CHARTS.length; i++) {
|
||||
try {
|
||||
return new CHARTS[i](canvas);
|
||||
} catch (e) {
|
||||
$log.warn([
|
||||
"Could not instantiate chart",
|
||||
CHARTS[i].name,
|
||||
";",
|
||||
e.message
|
||||
].join(" "));
|
||||
}
|
||||
}
|
||||
$log.warn("Cannot initialize mct-chart.");
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
152
platform/features/plot-reborn/src/draw/DrawWebGL.js
Normal file
152
platform/features/plot-reborn/src/draw/DrawWebGL.js
Normal file
@ -0,0 +1,152 @@
|
||||
/*global define,Float32Array*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
// WebGL shader sources (for drawing plain colors)
|
||||
var FRAGMENT_SHADER = [
|
||||
"precision mediump float;",
|
||||
"uniform vec4 uColor;",
|
||||
"void main(void) {",
|
||||
"gl_FragColor = uColor;",
|
||||
"}"
|
||||
].join('\n'),
|
||||
VERTEX_SHADER = [
|
||||
"attribute vec2 aVertexPosition;",
|
||||
"uniform vec2 uDimensions;",
|
||||
"uniform vec2 uOrigin;",
|
||||
"void main(void) {",
|
||||
"gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);",
|
||||
"}"
|
||||
].join('\n');
|
||||
|
||||
/**
|
||||
* Create a draw api utilizing WebGL.
|
||||
*
|
||||
* @constructor
|
||||
* @param {CanvasElement} canvas the canvas object to render upon
|
||||
* @throws {Error} an error is thrown if WebGL is unavailable.
|
||||
*/
|
||||
function DrawWebGL(canvas) {
|
||||
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"),
|
||||
vertexShader,
|
||||
fragmentShader,
|
||||
program,
|
||||
aVertexPosition,
|
||||
uColor,
|
||||
uDimensions,
|
||||
uOrigin,
|
||||
buffer;
|
||||
|
||||
// Ensure a context was actually available before proceeding
|
||||
if (!gl) {
|
||||
throw new Error("WebGL unavailable.");
|
||||
}
|
||||
|
||||
// Initialize shaders
|
||||
vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
||||
gl.shaderSource(vertexShader, VERTEX_SHADER);
|
||||
gl.compileShader(vertexShader);
|
||||
fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fragmentShader, FRAGMENT_SHADER);
|
||||
gl.compileShader(fragmentShader);
|
||||
|
||||
// Assemble vertex/fragment shaders into programs
|
||||
program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
gl.useProgram(program);
|
||||
|
||||
// Get locations for attribs/uniforms from the
|
||||
// shader programs (to pass values into shaders at draw-time)
|
||||
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
|
||||
uColor = gl.getUniformLocation(program, "uColor");
|
||||
uDimensions = gl.getUniformLocation(program, "uDimensions");
|
||||
uOrigin = gl.getUniformLocation(program, "uOrigin");
|
||||
gl.enableVertexAttribArray(aVertexPosition);
|
||||
|
||||
// Create a buffer to holds points which will be drawn
|
||||
buffer = gl.createBuffer();
|
||||
|
||||
// Use a line width of 2.0 for legibility
|
||||
gl.lineWidth(2.0);
|
||||
|
||||
// Enable blending, for smoothness
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Utility function to handle drawing of a buffer;
|
||||
// drawType will determine whether this is a box, line, etc.
|
||||
function doDraw(drawType, buf, color, points) {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, buf, gl.DYNAMIC_DRAW);
|
||||
gl.vertexAttribPointer(aVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.uniform4fv(uColor, color);
|
||||
gl.drawArrays(drawType, 0, points);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Clear the chart.
|
||||
*/
|
||||
clear: function () {
|
||||
// Set the viewport size; note that we use the width/height
|
||||
// that our WebGL context reports, which may be lower
|
||||
// resolution than the canvas we requested.
|
||||
gl.viewport(
|
||||
0,
|
||||
0,
|
||||
gl.drawingBufferWidth,
|
||||
gl.drawingBufferHeight
|
||||
);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT);
|
||||
},
|
||||
/**
|
||||
* Set the logical boundaries of the chart.
|
||||
* @param {number[]} dimensions the horizontal and
|
||||
* vertical dimensions of the chart
|
||||
* @param {number[]} origin the horizontal/vertical
|
||||
* origin of the chart
|
||||
*/
|
||||
setDimensions: function (dimensions, origin) {
|
||||
if (dimensions && dimensions.length > 0 &&
|
||||
origin && origin.length > 0) {
|
||||
gl.uniform2fv(uDimensions, dimensions);
|
||||
gl.uniform2fv(uOrigin, origin);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Draw the supplied buffer as a line strip (a sequence
|
||||
* of line segments), in the chosen color.
|
||||
* @param {Float32Array} buf the line strip to draw,
|
||||
* in alternating x/y positions
|
||||
* @param {number[]} color the color to use when drawing
|
||||
* the line, as an RGBA color where each element
|
||||
* is in the range of 0.0-1.0
|
||||
* @param {number} points the number of points to draw
|
||||
*/
|
||||
drawLine: function (buf, color, points) {
|
||||
doDraw(gl.LINE_STRIP, buf, color, points);
|
||||
},
|
||||
/**
|
||||
* Draw a rectangle extending from one corner to another,
|
||||
* in the chosen color.
|
||||
* @param {number[]} min the first corner of the rectangle
|
||||
* @param {number[]} max the opposite corner
|
||||
* @param {number[]} color the color to use when drawing
|
||||
* the rectangle, as an RGBA color where each element
|
||||
* is in the range of 0.0-1.0
|
||||
*/
|
||||
drawSquare: function (min, max, color) {
|
||||
doDraw(gl.TRIANGLE_FAN, new Float32Array(
|
||||
min.concat([min[0], max[1]]).concat(max).concat([max[0], min[1]])
|
||||
), color, 4);
|
||||
}
|
||||
};
|
||||
}
|
||||
return DrawWebGL;
|
||||
}
|
||||
);
|
75
platform/features/plot-reborn/src/lib/utils.js
Normal file
75
platform/features/plot-reborn/src/lib/utils.js
Normal file
@ -0,0 +1,75 @@
|
||||
/*global define*/
|
||||
|
||||
define(function() {
|
||||
"use strict";
|
||||
|
||||
var utils = {};
|
||||
|
||||
utils.boxPointsFromOppositeCorners = function(start, end) {
|
||||
// Given two points defining opposite corners of a square,
|
||||
// return an array of points containing all of the boxes' rectangles.
|
||||
return [
|
||||
start,
|
||||
{domain: start.domain, range: end.range},
|
||||
end,
|
||||
{domain: end.domain, range: start.range}
|
||||
];
|
||||
};
|
||||
|
||||
utils.oppositeCornersFromBoxPoints = function(boxPoints) {
|
||||
// Given an array of box points, return the topLeft and bottomRight points of the box.
|
||||
var topLeft = boxPoints.reduce(function(topLeft, currentPoint) {
|
||||
if (!topLeft) {
|
||||
return currentPoint;
|
||||
}
|
||||
if (currentPoint.domain <= topLeft.domain &&
|
||||
currentPoint.range >= topLeft.range) {
|
||||
return currentPoint;
|
||||
}
|
||||
return topLeft;
|
||||
});
|
||||
|
||||
var bottomRight = boxPoints.reduce(function(bottomRight, currentPoint) {
|
||||
if (!bottomRight) {
|
||||
return currentPoint;
|
||||
}
|
||||
if (currentPoint.domain >= bottomRight.domain &&
|
||||
currentPoint.range <= bottomRight.range) {
|
||||
return currentPoint;
|
||||
}
|
||||
return bottomRight;
|
||||
});
|
||||
|
||||
return {
|
||||
topLeft: topLeft,
|
||||
bottomRight: bottomRight
|
||||
};
|
||||
};
|
||||
|
||||
utils.elementPositionAsPlotPosition = function(elementPosition, elementBounds, viewport) {
|
||||
// Convert an (x, y) pair in element space to a
|
||||
// (domain, range) pair viewport.
|
||||
|
||||
// Element space has (0,0) as the topLeft corner, With x
|
||||
// increasing to the right and y increasing to the bottom.
|
||||
|
||||
var maxDomain = viewport.bottomRight.domain;
|
||||
var minDomain = viewport.topLeft.domain;
|
||||
var domainDenominator = maxDomain - minDomain;
|
||||
|
||||
var maxRange = viewport.topLeft.range;
|
||||
var minRange = viewport.bottomRight.range;
|
||||
var rangeDenominator = maxRange - minRange;
|
||||
|
||||
var xFraction = elementPosition.x / elementBounds.width;
|
||||
var yFraction = elementPosition.y / elementBounds.height;
|
||||
|
||||
return {
|
||||
domain: minDomain + domainDenominator * xFraction,
|
||||
range: maxRange - rangeDenominator * yFraction
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
return utils;
|
||||
});
|
154
platform/features/plot-reborn/src/services/ColorService.js
Normal file
154
platform/features/plot-reborn/src/services/ColorService.js
Normal file
@ -0,0 +1,154 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
define(
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
var COLOR_PALETTE = [
|
||||
[ 0x20, 0xB2, 0xAA ],
|
||||
[ 0x9A, 0xCD, 0x32 ],
|
||||
[ 0xFF, 0x8C, 0x00 ],
|
||||
[ 0xD2, 0xB4, 0x8C ],
|
||||
[ 0x40, 0xE0, 0xD0 ],
|
||||
[ 0x41, 0x69, 0xFF ],
|
||||
[ 0xFF, 0xD7, 0x00 ],
|
||||
[ 0x6A, 0x5A, 0xCD ],
|
||||
[ 0xEE, 0x82, 0xEE ],
|
||||
[ 0xCC, 0x99, 0x66 ],
|
||||
[ 0x99, 0xCC, 0xCC ],
|
||||
[ 0x66, 0xCC, 0x33 ],
|
||||
[ 0xFF, 0xCC, 0x00 ],
|
||||
[ 0xFF, 0x66, 0x33 ],
|
||||
[ 0xCC, 0x66, 0xFF ],
|
||||
[ 0xFF, 0x00, 0x66 ],
|
||||
[ 0xFF, 0xFF, 0x00 ],
|
||||
[ 0x80, 0x00, 0x80 ],
|
||||
[ 0x00, 0x86, 0x8B ],
|
||||
[ 0x00, 0x8A, 0x00 ],
|
||||
[ 0xFF, 0x00, 0x00 ],
|
||||
[ 0x00, 0x00, 0xFF ],
|
||||
[ 0xF5, 0xDE, 0xB3 ],
|
||||
[ 0xBC, 0x8F, 0x8F ],
|
||||
[ 0x46, 0x82, 0xB4 ],
|
||||
[ 0xFF, 0xAF, 0xAF ],
|
||||
[ 0x43, 0xCD, 0x80 ],
|
||||
[ 0xCD, 0xC1, 0xC5 ],
|
||||
[ 0xA0, 0x52, 0x2D ],
|
||||
[ 0x64, 0x95, 0xED ]
|
||||
];
|
||||
|
||||
/**
|
||||
* A representation of a color that allows conversions between different
|
||||
* formats.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Color(integerArray) {
|
||||
this.integerArray = integerArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return color as a three element array of RGB values, where each value
|
||||
* is a integer in the range of 0-255.
|
||||
*
|
||||
* @return {number[]} the color, as integer RGB values
|
||||
*/
|
||||
Color.prototype.asIntegerArray = function () {
|
||||
return this.integerArray.map(function (c) {
|
||||
return c;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return color as a string using #-prefixed six-digit RGB hex notation
|
||||
* (e.g. #FF0000). See http://www.w3.org/TR/css3-color/#rgb-color.
|
||||
*
|
||||
* @return {string} the color, as a style-friendly string
|
||||
*/
|
||||
|
||||
Color.prototype.asHexString = function () {
|
||||
return '#' + this.integerArray.map(function (c) {
|
||||
return (c < 16 ? '0' : '') + c.toString(16);
|
||||
}).join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Return color as a RGBA float array.
|
||||
*
|
||||
* This format is present specifically to support use with
|
||||
* WebGL, which expects colors of that form.
|
||||
*
|
||||
* @return {number[]} the color, as floating-point RGBA values
|
||||
*/
|
||||
Color.prototype.asRGBAArray = function () {
|
||||
return this.integerArray.map(function (c) {
|
||||
return c / 255.0;
|
||||
}).concat([1]);
|
||||
};
|
||||
|
||||
/**
|
||||
* A color palette stores a set of colors and allows for different
|
||||
* methods of color allocation.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function ColorPalette() {
|
||||
this.nextColor = 0;
|
||||
this.colors = COLOR_PALETTE.map(function (color) {
|
||||
return new Color(color);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Color} the next unused color in the palette. If all colors
|
||||
* have been allocated, it will wrap around.
|
||||
*/
|
||||
ColorPalette.prototype.getNextColor = function () {
|
||||
var color = this.colors[this.nextColor % this.colors.length];
|
||||
this.nextColor++;
|
||||
return color;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index the index of the color to return. An index
|
||||
* value larger than the size of the index will wrap around.
|
||||
* @returns {Color}
|
||||
*/
|
||||
ColorPalette.prototype.getColor = function (index) {
|
||||
return this.colors[index % this.colors.length];
|
||||
};
|
||||
|
||||
|
||||
function ColorService() {}
|
||||
|
||||
ColorService.prototype.ColorPalette = ColorPalette;
|
||||
ColorService.prototype.Color = Color;
|
||||
|
||||
function getColorService() {
|
||||
return new ColorService();
|
||||
}
|
||||
|
||||
return getColorService;
|
||||
}
|
||||
);
|
@ -0,0 +1,109 @@
|
||||
/*****************************************************************************
|
||||
* 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,xit,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/PlotController"],
|
||||
function (PlotController) {
|
||||
"use strict";
|
||||
|
||||
describe("The plot controller", function () {
|
||||
var mockScope,
|
||||
mockColorService,
|
||||
mockAgentService,
|
||||
mockTopLeft,
|
||||
mockBottomRight,
|
||||
mockViewport,
|
||||
mockAxes,
|
||||
controller;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$watch", "$on", "viewport", "axes" ]
|
||||
);
|
||||
|
||||
mockColorService = jasmine.createSpyObj(
|
||||
"colorService", [ "ColorPalette" ]
|
||||
);
|
||||
|
||||
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
|
||||
|
||||
mockViewport = jasmine.createSpyObj(
|
||||
"viewport", [ "bottomRight, topLeft" ]
|
||||
);
|
||||
|
||||
mockAxes = jasmine.createSpyObj(
|
||||
"axes", [ "domain" ]
|
||||
);
|
||||
|
||||
mockTopLeft = {
|
||||
range: 1,
|
||||
domain: 1
|
||||
}
|
||||
mockBottomRight = {
|
||||
range: 1,
|
||||
domain: 1
|
||||
}
|
||||
|
||||
mockViewport.topLeft = mockTopLeft;
|
||||
mockViewport.bottomRight = mockBottomRight;
|
||||
|
||||
mockScope.axes = mockAxes;
|
||||
|
||||
mockAgentService.isMobile.andReturn(false);
|
||||
|
||||
controller = new PlotController(
|
||||
mockScope,
|
||||
mockColorService,
|
||||
mockAgentService
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("Performs scope call when viewport stops changing", function () {
|
||||
|
||||
mockAgentService.isMobile.andReturn(true);
|
||||
|
||||
// Calls end viewport with no snap-to-right opportunity and on mobile
|
||||
mockScope.$on.calls[1].args[1]("event", mockViewport);
|
||||
|
||||
mockBottomRight = {
|
||||
range: 1,
|
||||
domain: +new Date()
|
||||
}
|
||||
|
||||
mockViewport.bottomRight = mockBottomRight;
|
||||
|
||||
controller = new PlotController(
|
||||
mockScope,
|
||||
mockColorService,
|
||||
mockAgentService
|
||||
);
|
||||
|
||||
// Calls end viewport with snap-to-right opportunity and on mobile
|
||||
mockScope.$on.calls[1].args[1]("event", mockViewport);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -0,0 +1,60 @@
|
||||
/*****************************************************************************
|
||||
* 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,xit,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/directives/MCTChart"],
|
||||
function (MCTChart) {
|
||||
"use strict";
|
||||
|
||||
describe("The MCT Chart directive", function () {
|
||||
var mockInterval,
|
||||
mockLog,
|
||||
mockAgentService,
|
||||
mockScope,
|
||||
mockElement,
|
||||
mockCanvas,
|
||||
mctChart;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockInterval =
|
||||
jasmine.createSpyObj("$interval", [ "cancel" ]);
|
||||
mockLog = jasmine.createSpyObj("$log", [ "warn" ]);
|
||||
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
|
||||
mockCanvas = jasmine.createSpyObj("canvas", [ "getContext", "addEventListener" ]);
|
||||
mockScope =
|
||||
jasmine.createSpyObj("$scope", [ "$on", "$watch", "series", "viewport", "rectangles" ]);
|
||||
mockElement =
|
||||
jasmine.createSpyObj("$element", [ "find" ]);
|
||||
|
||||
mctChart = new MCTChart(mockInterval, mockAgentService);
|
||||
});
|
||||
|
||||
it("Calls", function() {
|
||||
mockElement.find.andReturn([mockCanvas]);
|
||||
|
||||
//mctChart.link(mockScope, mockElement);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
105
platform/features/plot-reborn/test/directives/MCTPinchSpec.js
Normal file
105
platform/features/plot-reborn/test/directives/MCTPinchSpec.js
Normal file
@ -0,0 +1,105 @@
|
||||
/*****************************************************************************
|
||||
* 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,xit,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/directives/MCTPinch"],
|
||||
function (MCTPinch) {
|
||||
"use strict";
|
||||
|
||||
describe("The MCT Pinch directive", function () {
|
||||
var mockScope,
|
||||
mockElement,
|
||||
mockAgentService,
|
||||
mctPinch,
|
||||
mockEvent,
|
||||
mockTouches,
|
||||
mockChangedTouches,
|
||||
mockTarget,
|
||||
mockTouchEvent;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj("$scope", [ "$emit", "$on" ]);
|
||||
mockElement = jasmine.createSpyObj("element", [ "on", "off" ]);
|
||||
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
|
||||
mockEvent = jasmine.createSpyObj("event", [ "touches", "changedTouches", "preventDefault", "target" ]);
|
||||
mockTouchEvent = jasmine.createSpyObj("event",
|
||||
[ "clientX", "clientY" ]);
|
||||
mockTarget = jasmine.createSpyObj("event.target", ["getBoundingClientRect"]);
|
||||
|
||||
mockAgentService.isMobile.andReturn(true);
|
||||
|
||||
mctPinch = new MCTPinch(mockAgentService);
|
||||
mctPinch.link(mockScope, mockElement);
|
||||
|
||||
// Sets the amount of touches and changedTouches done
|
||||
// to 1, therefore a pan
|
||||
mockTouches = [mockTouchEvent];
|
||||
mockChangedTouches = [mockTouchEvent];
|
||||
|
||||
// Sets mockEvent touch information and bounds
|
||||
mockEvent.touches = mockTouches;
|
||||
mockEvent.changedTouches = mockChangedTouches;
|
||||
mockEvent.target = mockTarget;
|
||||
});
|
||||
|
||||
it("fires single finger pan touch events: start, change, end", function() {
|
||||
// Fires touch start
|
||||
mockElement.on.calls[0].args[1](mockEvent);
|
||||
// Fires touch move
|
||||
mockElement.on.calls[1].args[1](mockEvent);
|
||||
// Fires touch end
|
||||
mockElement.on.calls[2].args[1](mockEvent);
|
||||
// Fires touch cancel
|
||||
mockElement.on.calls[3].args[1](mockEvent);
|
||||
});
|
||||
|
||||
it("fires two finger pinch touch events: start, change, end", function() {
|
||||
|
||||
// Sets the amount of touches and changedTouches done
|
||||
// to 2, therefore a pinch
|
||||
mockTouches = [mockTouchEvent, mockTouchEvent];
|
||||
mockChangedTouches = [mockTouchEvent, mockTouchEvent];
|
||||
|
||||
// Re-sets mockEvent touch information and bounds
|
||||
mockEvent.touches = mockTouches;
|
||||
mockEvent.changedTouches = mockChangedTouches;
|
||||
mockEvent.target = mockTarget;
|
||||
|
||||
// Fires touch start
|
||||
mockElement.on.calls[0].args[1](mockEvent);
|
||||
// Fires touch move
|
||||
mockElement.on.calls[1].args[1](mockEvent);
|
||||
// Fires touch end
|
||||
mockElement.on.calls[2].args[1](mockEvent);
|
||||
// Fires touch cancel
|
||||
mockElement.on.calls[3].args[1](mockEvent);
|
||||
});
|
||||
|
||||
// Checks the destroy command
|
||||
it("tests for destruction of the $scope", function() {
|
||||
mockScope.$on.calls[0].args[1]();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
121
platform/features/plot-reborn/test/directives/MCTPlotSpec.js
Normal file
121
platform/features/plot-reborn/test/directives/MCTPlotSpec.js
Normal file
@ -0,0 +1,121 @@
|
||||
/*****************************************************************************
|
||||
* 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,xit,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/directives/MCTPlot"],
|
||||
function (MCTPlot) {
|
||||
"use strict";
|
||||
|
||||
describe("The MCT Pinch directive", function () {
|
||||
var mockScope,
|
||||
mockElement,
|
||||
mockCanvas,
|
||||
mockTouch,
|
||||
mockTouchEvent,
|
||||
mockTouchPair,
|
||||
mockBounds,
|
||||
mockBoundsEvent,
|
||||
mockTarget,
|
||||
mockUtils,
|
||||
mockMidpoint,
|
||||
mockDistance,
|
||||
mctPlot;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj("$scope", [
|
||||
"axes", "viewport", "rectangles", "mouseCoordinates",
|
||||
"$broadcast", "displayableRange", "displayableDomain",
|
||||
"$emit", "$on", "$watchCollection" ]);
|
||||
mockElement = jasmine.createSpyObj("$element", [ "find" ]);
|
||||
mockCanvas = jasmine.createSpyObj("canvas", [ "on", "off", "removeClass", "addClass" ]);
|
||||
mockBoundsEvent = jasmine.createSpyObj("event", [ "touches", "changedTouches", "preventDefault", "target" ]);
|
||||
mockTarget = jasmine.createSpyObj("event.target", ["getBoundingClientRect"]);
|
||||
mockMidpoint = jasmine.createSpyObj("touch.midpoint", ["clientX", "clientY"]);
|
||||
mockTouchEvent = jasmine.createSpyObj("event",
|
||||
[ "clientX", "clientY" ]);
|
||||
mockDistance = jasmine.createSpy("touch.distance");
|
||||
mockUtils = jasmine.createSpyObj("utils", [ "elementPositionAsPlotPosition" ]);
|
||||
|
||||
mockTouchPair = [mockTouchEvent, mockTouchEvent];
|
||||
|
||||
mockBoundsEvent.target = mockTarget;
|
||||
mockBounds = mockTarget.getBoundingClientRect();
|
||||
|
||||
mockElement.find.andReturn(mockCanvas);
|
||||
|
||||
mctPlot = new MCTPlot();
|
||||
|
||||
mctPlot.link(mockScope, mockElement);
|
||||
});
|
||||
|
||||
it("Start Pinch", function() {
|
||||
//console.log(mockScope.$on.calls[0]);
|
||||
mockTouch = {
|
||||
touches: mockTouchPair,
|
||||
bounds: mockBounds,
|
||||
midpoint: mockMidpoint,
|
||||
distance: mockDistance
|
||||
|
||||
};
|
||||
//mockScope.$on.calls[0].args[1]("event", mockTouch);
|
||||
});
|
||||
|
||||
it("Change Pinch", function() {
|
||||
mockTouch = {
|
||||
touches: mockTouchPair,
|
||||
bounds: mockBounds,
|
||||
midpoint: mockMidpoint,
|
||||
distance: mockDistance
|
||||
|
||||
};
|
||||
//console.log(mockScope.$on.calls[1]);
|
||||
//mockScope.$on.calls[1].args[1]();
|
||||
});
|
||||
|
||||
it("Start Pan", function() {
|
||||
mockTouch = {
|
||||
touch: [mockTouchEvent],
|
||||
bounds: mockBounds
|
||||
};
|
||||
//console.log(mockScope.$on.calls[2]);
|
||||
//mockScope.$on.calls[2].args[1]();
|
||||
});
|
||||
|
||||
it("Change Pan", function() {
|
||||
mockTouch = {
|
||||
touch: [mockTouchEvent],
|
||||
bounds: mockBounds
|
||||
};
|
||||
//console.log(mockScope.$on.calls[3]);
|
||||
//mockScope.$on.calls[3].args[1]();
|
||||
});
|
||||
|
||||
it("Touch End", function() {
|
||||
//console.log(mockScope.$on.calls[4]);
|
||||
//mockScope.$on.calls[4].args[1]();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
7
platform/features/plot-reborn/test/suite.json
Normal file
7
platform/features/plot-reborn/test/suite.json
Normal file
@ -0,0 +1,7 @@
|
||||
[
|
||||
"controllers/PlotController",
|
||||
"directives/MCTChart",
|
||||
"directives/MCTPlot",
|
||||
"directives/MCTPinch"
|
||||
]
|
||||
|
@ -25,6 +25,7 @@
|
||||
<div class="gl-plot"
|
||||
ng-style="{ height: 100 / plot.getSubPlots().length + '%'}"
|
||||
ng-repeat="subplot in plot.getSubPlots()">
|
||||
<!-- mct-pan="handlePan(position)">-->
|
||||
<div class="gl-plot-legend">
|
||||
<!-- ng-class is temporarily hard-coded in next element -->
|
||||
<span
|
||||
@ -42,7 +43,7 @@
|
||||
<div
|
||||
class="gl-plot-coords"
|
||||
ng-if="subplot.isHovering() && subplot.getHoverCoordinates()"
|
||||
>
|
||||
>
|
||||
{{subplot.getHoverCoordinates()}}
|
||||
</div>
|
||||
|
||||
|
@ -22,8 +22,7 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* This bundle adds a "Plot" view for numeric telemetry data.
|
||||
* @namespace platform/features/plot
|
||||
* Module defining PlotController. Created by vwoeltje on 11/12/14.
|
||||
*/
|
||||
define(
|
||||
[
|
||||
@ -51,7 +50,6 @@ define(
|
||||
* * Handling user interactions.
|
||||
* * Deciding what needs to be drawn in the chart area.
|
||||
*
|
||||
* @memberof platform/features/plot
|
||||
* @constructor
|
||||
*/
|
||||
function PlotController(
|
||||
@ -61,11 +59,15 @@ define(
|
||||
throttle,
|
||||
PLOT_FIXED_DURATION
|
||||
) {
|
||||
var self = this,
|
||||
subPlotFactory = new SubPlotFactory(telemetryFormatter),
|
||||
var subPlotFactory = new SubPlotFactory(telemetryFormatter),
|
||||
modeOptions = new PlotModeOptions([], subPlotFactory),
|
||||
subplots = [],
|
||||
cachedObjects = [],
|
||||
limitTracker,
|
||||
updater,
|
||||
handle;
|
||||
handle,
|
||||
scheduleUpdate,
|
||||
domainOffset;
|
||||
|
||||
// Populate the scope with axis information (specifically, options
|
||||
// available for each axis.)
|
||||
@ -87,13 +89,18 @@ define(
|
||||
function setupModes(telemetryObjects) {
|
||||
if (cachedObjects !== telemetryObjects) {
|
||||
cachedObjects = telemetryObjects;
|
||||
self.modeOptions = new PlotModeOptions(
|
||||
modeOptions = new PlotModeOptions(
|
||||
telemetryObjects || [],
|
||||
subPlotFactory
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update all sub-plots
|
||||
function update() {
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
// Reinstantiate the plot updater (e.g. because we have a
|
||||
// new subscription.) This will clear the plot.
|
||||
function recreateUpdater() {
|
||||
@ -103,7 +110,7 @@ define(
|
||||
($scope.axes[1].active || {}).key,
|
||||
PLOT_FIXED_DURATION
|
||||
);
|
||||
self.limitTracker = new PlotLimitTracker(
|
||||
limitTracker = new PlotLimitTracker(
|
||||
handle,
|
||||
($scope.axes[1].active || {}).key
|
||||
);
|
||||
@ -116,19 +123,19 @@ define(
|
||||
}
|
||||
if (updater) {
|
||||
updater.update();
|
||||
self.modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
}
|
||||
if (self.limitTracker) {
|
||||
self.limitTracker.update();
|
||||
if (limitTracker) {
|
||||
limitTracker.update();
|
||||
}
|
||||
self.update();
|
||||
update();
|
||||
}
|
||||
|
||||
// Display new historical data as it becomes available
|
||||
function addHistoricalData(domainObject, series) {
|
||||
updater.addHistorical(domainObject, series);
|
||||
self.modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
self.update();
|
||||
modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
update();
|
||||
}
|
||||
|
||||
// Issue a new request for historical telemetry
|
||||
@ -165,120 +172,105 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
this.modeOptions = new PlotModeOptions([], subPlotFactory);
|
||||
this.updateValues = updateValues;
|
||||
|
||||
// Create a throttled update function
|
||||
this.scheduleUpdate = throttle(function () {
|
||||
self.modeOptions.getModeHandler().getSubPlots()
|
||||
.forEach(updateSubplot);
|
||||
});
|
||||
|
||||
// Subscribe to telemetry when a domain object becomes available
|
||||
$scope.$watch('domainObject', subscribe);
|
||||
|
||||
// Unsubscribe when the plot is destroyed
|
||||
$scope.$on("$destroy", releaseSubscription);
|
||||
|
||||
// Create a throttled update function
|
||||
scheduleUpdate = throttle(function () {
|
||||
modeOptions.getModeHandler().getSubPlots()
|
||||
.forEach(updateSubplot);
|
||||
});
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get the color (as a style-friendly string) to use
|
||||
* for plotting the trace at the specified index.
|
||||
* @param {number} index the index of the trace
|
||||
* @returns {string} the color, in #RRGGBB form
|
||||
*/
|
||||
getColor: function (index) {
|
||||
return PlotPalette.getStringColor(index);
|
||||
},
|
||||
/**
|
||||
* Check if the plot is zoomed or panned out
|
||||
* of its default state (to determine whether back/unzoom
|
||||
* controls should be shown)
|
||||
* @returns {boolean} true if not in default state
|
||||
*/
|
||||
isZoomed: function () {
|
||||
return modeOptions.getModeHandler().isZoomed();
|
||||
},
|
||||
/**
|
||||
* Undo the most recent pan/zoom change and restore
|
||||
* the prior state.
|
||||
*/
|
||||
stepBackPanZoom: function () {
|
||||
return modeOptions.getModeHandler().stepBackPanZoom();
|
||||
},
|
||||
/**
|
||||
* Undo all pan/zoom changes and restore the initial state.
|
||||
*/
|
||||
unzoom: function () {
|
||||
return modeOptions.getModeHandler().unzoom();
|
||||
},
|
||||
/**
|
||||
* Get the mode options (Stacked/Overlaid) that are applicable
|
||||
* for this plot.
|
||||
*/
|
||||
getModeOptions: function () {
|
||||
return modeOptions.getModeOptions();
|
||||
},
|
||||
/**
|
||||
* Get the current mode that is applicable to this plot. This
|
||||
* will include key, name, and glyph fields.
|
||||
*/
|
||||
getMode: function () {
|
||||
return modeOptions.getMode();
|
||||
},
|
||||
/**
|
||||
* Set the mode which should be active in this plot.
|
||||
* @param mode one of the mode options returned from
|
||||
* getModeOptions()
|
||||
*/
|
||||
setMode: function (mode) {
|
||||
modeOptions.setMode(mode);
|
||||
updateValues();
|
||||
},
|
||||
/**
|
||||
* Get all individual plots contained within this Plot view.
|
||||
* (Multiple may be contained when in Stacked mode).
|
||||
* @returns {SubPlot[]} all subplots in this Plot view
|
||||
*/
|
||||
getSubPlots: function () {
|
||||
return modeOptions.getModeHandler().getSubPlots();
|
||||
},
|
||||
/**
|
||||
* Get the CSS class to apply to the legend for this domain
|
||||
* object; this will reflect limit state.
|
||||
* @returns {string} the CSS class
|
||||
*/
|
||||
getLegendClass: function (telemetryObject) {
|
||||
return limitTracker &&
|
||||
limitTracker.getLegendClass(telemetryObject);
|
||||
},
|
||||
/**
|
||||
* Explicitly update all plots.
|
||||
*/
|
||||
update: update,
|
||||
/**
|
||||
* Check if a request is pending (to show the wait spinner)
|
||||
*/
|
||||
isRequestPending: function () {
|
||||
// Placeholder; this should reflect request state
|
||||
// when requesting historical telemetry
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color (as a style-friendly string) to use
|
||||
* for plotting the trace at the specified index.
|
||||
* @param {number} index the index of the trace
|
||||
* @returns {string} the color, in #RRGGBB form
|
||||
*/
|
||||
PlotController.prototype.getColor = function (index) {
|
||||
return PlotPalette.getStringColor(index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the plot is zoomed or panned out
|
||||
* of its default state (to determine whether back/unzoom
|
||||
* controls should be shown)
|
||||
* @returns {boolean} true if not in default state
|
||||
*/
|
||||
PlotController.prototype.isZoomed = function () {
|
||||
return this.modeOptions.getModeHandler().isZoomed();
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo the most recent pan/zoom change and restore
|
||||
* the prior state.
|
||||
*/
|
||||
PlotController.prototype.stepBackPanZoom = function () {
|
||||
return this.modeOptions.getModeHandler().stepBackPanZoom();
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo all pan/zoom changes and restore the initial state.
|
||||
*/
|
||||
PlotController.prototype.unzoom = function () {
|
||||
return this.modeOptions.getModeHandler().unzoom();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the mode options (Stacked/Overlaid) that are applicable
|
||||
* for this plot.
|
||||
*/
|
||||
PlotController.prototype.getModeOptions = function () {
|
||||
return this.modeOptions.getModeOptions();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current mode that is applicable to this plot. This
|
||||
* will include key, name, and glyph fields.
|
||||
*/
|
||||
PlotController.prototype.getMode = function () {
|
||||
return this.modeOptions.getMode();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the mode which should be active in this plot.
|
||||
* @param mode one of the mode options returned from
|
||||
* getModeOptions()
|
||||
*/
|
||||
PlotController.prototype.setMode = function (mode) {
|
||||
this.modeOptions.setMode(mode);
|
||||
this.updateValues();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all individual plots contained within this Plot view.
|
||||
* (Multiple may be contained when in Stacked mode).
|
||||
* @returns {SubPlot[]} all subplots in this Plot view
|
||||
*/
|
||||
PlotController.prototype.getSubPlots = function () {
|
||||
return this.modeOptions.getModeHandler().getSubPlots();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the CSS class to apply to the legend for this domain
|
||||
* object; this will reflect limit state.
|
||||
* @returns {string} the CSS class
|
||||
*/
|
||||
PlotController.prototype.getLegendClass = function (telemetryObject) {
|
||||
return this.limitTracker &&
|
||||
this.limitTracker.getLegendClass(telemetryObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Explicitly update all plots.
|
||||
*/
|
||||
PlotController.prototype.update = function () {
|
||||
this.scheduleUpdate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a request is pending (to show the wait spinner)
|
||||
*/
|
||||
PlotController.prototype.isRequestPending = function () {
|
||||
// Placeholder; this should reflect request state
|
||||
// when requesting historical telemetry
|
||||
return false;
|
||||
};
|
||||
|
||||
return PlotController;
|
||||
}
|
||||
);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user