Compare commits
	
		
			292 Commits
		
	
	
		
			git-info-f
			...
			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