Compare commits
	
		
			292 Commits
		
	
	
		
			tree-1.7.3
			...
			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