diff --git a/index.html b/index.html index 1405bcec24..66cd66e6c4 100644 --- a/index.html +++ b/index.html @@ -21,68 +21,69 @@ --> - - - - - - + - - - - - - - - -
-
-
- + ] + })); + openmct.install(openmct.plugins.SummaryWidget()); + openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0}); + openmct.time.timeSystem('utc'); + openmct.start(); + }); + + + + + + + + + +
+
+
+ diff --git a/platform/commonUI/browse/bundle.js b/platform/commonUI/browse/bundle.js index f01e2d29e3..975f3cdb0f 100644 --- a/platform/commonUI/browse/bundle.js +++ b/platform/commonUI/browse/bundle.js @@ -113,7 +113,8 @@ define([ "agentService", "$window", "$location", - "$attrs" + "$attrs", + "navigationService" ] }, { diff --git a/platform/commonUI/browse/src/PaneController.js b/platform/commonUI/browse/src/PaneController.js index 8c75771815..4e49d0be6e 100644 --- a/platform/commonUI/browse/src/PaneController.js +++ b/platform/commonUI/browse/src/PaneController.js @@ -24,14 +24,14 @@ define( [], function () { - + var navigationListenerAdded = false; /** * Controller to provide the ability to show/hide the tree in * Browse mode. * @constructor * @memberof platform/commonUI/browse */ - function PaneController($scope, agentService, $window, $location, $attrs) { + function PaneController($scope, agentService, $window, $location, $attrs, navigationService) { var self = this; this.agentService = agentService; var hideParameterPresent = $location.search().hasOwnProperty($attrs.hideParameter); @@ -61,6 +61,11 @@ define( self.state = false; } }; + + if (navigationService && navigationService.addListener && !navigationListenerAdded) { + navigationService.addListener(this.callback); + navigationListenerAdded = true; + } } /** diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index 9e6efaf262..19db4463e0 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -327,7 +327,8 @@ define([ "key": "mctDrag", "implementation": MCTDrag, "depends": [ - "$document" + "$document", + "agentService" ] }, { diff --git a/platform/commonUI/general/res/sass/_constants.scss b/platform/commonUI/general/res/sass/_constants.scss index 6246b8fbdc..4d603e13e7 100644 --- a/platform/commonUI/general/res/sass/_constants.scss +++ b/platform/commonUI/general/res/sass/_constants.scss @@ -81,7 +81,7 @@ $tabularTdPadLR: $itemPadLR; $tabularTdPadTB: 2px; /*************** Imagery */ $imageMainControlBarH: 25px; -$imageThumbsD: 120px; +$imageThumbsD: 100px; $imageThumbsWrapperH: 155px; $imageThumbPad: 1px; /*************** Ticks */ diff --git a/platform/commonUI/general/res/sass/features/_imagery.scss b/platform/commonUI/general/res/sass/features/_imagery.scss index 21b269b3fa..67647d23ae 100644 --- a/platform/commonUI/general/res/sass/features/_imagery.scss +++ b/platform/commonUI/general/res/sass/features/_imagery.scss @@ -205,3 +205,14 @@ display: none; } } + +/*************************************** MOBILE */ +body.mobile.phone { + .t-imagery { + .l-image-main-wrapper, + .l-image-thumbs-wrapper { + //background: red; + min-height: 10px !important; + } + } +} diff --git a/platform/commonUI/general/res/sass/mobile/_layout.scss b/platform/commonUI/general/res/sass/mobile/_layout.scss index 19db279dc6..241fedfe4d 100644 --- a/platform/commonUI/general/res/sass/mobile/_layout.scss +++ b/platform/commonUI/general/res/sass/mobile/_layout.scss @@ -26,8 +26,8 @@ body.mobile { } .pane.right.items { - //@include test(); @include slMenuTransitions; + left: 0 !important; margin-left: 0 !important; .holder-object-and-inspector { @include slMenuTransitions; @@ -47,12 +47,10 @@ body.mobile { right: $bodyMargin !important; } -// When the tree is hidden, these are the - // classes used for the left menu and the - // right representation. + // Assume landscape layout or either orientation for tablet + // Phone portrait overrides below via media query .pane-tree-hidden { - // Sets the left tree menu when the tree - // is hidden. + // Sets the left tree menu when the tree is hidden. .pane.left.treeview { @include trans-prop-nice(opacity, 150ms); opacity: 0 !important; @@ -73,12 +71,12 @@ body.mobile { .pane.left.treeview { @include trans-prop-nice(opacity, 250ms, $delay: 250ms); @include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%)); - right: auto !important; width: $proporMenuWithView !important; + right: auto !important; } // Sets the right representation when the tree is shown. .pane.right.items { - left: $proporMenuWithView !important; + transform: translateX($proporMenuWithView); } } @@ -92,12 +90,19 @@ body.mobile { } .object-browse-bar { - &.t-primary { margin-left: 45px; } + &.t-primary { + margin-left: 45px; + + .title-label { + // Prevent inline editing of the object title in the main view in mobile + pointer-events: none; + } + } .context-available { + font-size: 0.9em; opacity: 1 !important; } .view-switcher { - margin-right: 0 !important; .title-label { // Hide the name in mobile display: none; @@ -131,16 +136,17 @@ body.mobile { } } -body.phone.portrait { - .pane-tree-showing { - .pane.left.treeview { - width: $proporMenuOnly !important; - } - .pane.right.items { - left: 0 !important; - transform: translateX($proporMenuOnly); - .holder-object-and-inspector { - opacity: 0; +@media only screen and (max-device-width: $phoMaxW) and (orientation: portrait) { + body.mobile { + .pane-tree-showing { + .pane.left.treeview { + width: $proporMenuOnly !important; + } + .pane.right.items { + transform: translateX($proporMenuOnly); + .holder-object-and-inspector { + opacity: 0; + } } } } diff --git a/platform/commonUI/general/res/sass/startup-base.scss b/platform/commonUI/general/res/sass/startup-base.scss index f25ed0df07..8395000f30 100644 --- a/platform/commonUI/general/res/sass/startup-base.scss +++ b/platform/commonUI/general/res/sass/startup-base.scss @@ -28,7 +28,8 @@ $output-bourbon-deprecation-warnings: false; } body, html { - overflow: hidden; + height: 100%; + width: 100%; } .l-splash-holder { diff --git a/platform/commonUI/general/res/sass/user-environ/_layout.scss b/platform/commonUI/general/res/sass/user-environ/_layout.scss index f506b92f6c..29af0a8a4d 100644 --- a/platform/commonUI/general/res/sass/user-environ/_layout.scss +++ b/platform/commonUI/general/res/sass/user-environ/_layout.scss @@ -20,6 +20,7 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ +.user-environ, .browse-area, .edit-area, .editor { @@ -47,6 +48,9 @@ } .user-environ { + height: 100%; + width: 100%; + overflow: hidden !important; .browse-area, .editor { top: 0; left: 0; right: 0; bottom: $ueFooterH; diff --git a/platform/commonUI/general/src/directives/MCTDrag.js b/platform/commonUI/general/src/directives/MCTDrag.js index 16264fd173..700e83d409 100644 --- a/platform/commonUI/general/src/directives/MCTDrag.js +++ b/platform/commonUI/general/src/directives/MCTDrag.js @@ -46,7 +46,7 @@ define( * @constructor * */ - function MCTDrag($document) { + function MCTDrag($document, agentService) { // Link; install event handlers. function link(scope, element, attrs) { @@ -55,10 +55,26 @@ define( // only be attached to the element being linked, as the // mouse may leave this element during the drag. var body = $document.find('body'), + isMobile = agentService.isMobile(), + touchEvents, initialPosition, $event, delta; + if (isMobile) { + touchEvents = { + start: 'touchstart', + end: 'touchend', + move: 'touchmove' + }; + } else { + touchEvents = { + start: 'mousedown', + end: "mouseup", + move: "mousemove" + }; + } + // Utility function to cause evaluation of mctDrag, // mctDragUp, etc function fireListener(name) { @@ -103,8 +119,8 @@ define( // Called only when the drag ends (on mouseup) function endDrag(event) { // Detach event handlers - body.off("mouseup", endDrag); - body.off("mousemove", continueDrag); + body.off(touchEvents.end, endDrag); + body.off(touchEvents.move, continueDrag); // Also call continueDrag, to fire mctDrag // and do its usual position update @@ -125,8 +141,8 @@ define( // Listen for mouse events at the body level, // since the mouse may leave the element during // the drag. - body.on("mouseup", endDrag); - body.on("mousemove", continueDrag); + body.on(touchEvents.end, endDrag); + body.on(touchEvents.move, continueDrag); // Set an initial position updatePosition(event); @@ -141,8 +157,8 @@ define( return false; } - // Listen for mousedown on the element - element.on("mousedown", startDrag); + // Listen for start event on the element + element.on(touchEvents.start, startDrag); } return { diff --git a/platform/commonUI/general/test/directives/MCTDragSpec.js b/platform/commonUI/general/test/directives/MCTDragSpec.js index 46c1d754bc..1a23d09dbc 100644 --- a/platform/commonUI/general/test/directives/MCTDragSpec.js +++ b/platform/commonUI/general/test/directives/MCTDragSpec.js @@ -26,8 +26,9 @@ define( var JQLITE_METHODS = ["on", "off", "find"]; - describe("The mct-drag directive", function () { + describe("The mct-drag directive in Mobile", function () { var mockDocument, + mockAgentService, mockScope, mockElement, testAttrs, @@ -45,6 +46,8 @@ define( beforeEach(function () { mockDocument = jasmine.createSpyObj("$document", JQLITE_METHODS); + mockAgentService = + jasmine.createSpyObj("agentService", ["isMobile"]); mockScope = jasmine.createSpyObj("$scope", ["$eval", "$apply"]); mockElement = @@ -59,8 +62,137 @@ define( }; mockDocument.find.andReturn(mockBody); + mockAgentService.isMobile.andReturn(true); - mctDrag = new MCTDrag(mockDocument); + mctDrag = new MCTDrag(mockDocument, mockAgentService); + mctDrag.link(mockScope, mockElement, testAttrs); + }); + + it("is valid as an attribute", function () { + expect(mctDrag.restrict).toEqual("A"); + }); + + it("listens for touchstart on its element", function () { + expect(mockElement.on).toHaveBeenCalledWith( + "touchstart", + jasmine.any(Function) + ); + + // Verify no interactions with body as well + expect(mockBody.on).not.toHaveBeenCalled(); + }); + + it("invokes mctDragDown when dragging begins", function () { + var event = testEvent(42, 60); + mockElement.on.mostRecentCall.args[1](event); + expect(mockScope.$eval).toHaveBeenCalledWith( + testAttrs.mctDragDown, + { delta: [0, 0], $event: event } + ); + }); + + it("listens for touchmove after dragging begins", function () { + mockElement.on.mostRecentCall.args[1](testEvent(42, 60)); + expect(mockBody.on).toHaveBeenCalledWith( + "touchmove", + jasmine.any(Function) + ); + expect(mockBody.on).toHaveBeenCalledWith( + "touchend", + jasmine.any(Function) + ); + }); + + it("invokes mctDrag expression during drag", function () { + var event; + + mockElement.on.mostRecentCall.args[1](testEvent(42, 60)); + + // Find and invoke the touchmove listener + mockBody.on.calls.forEach(function (call) { + if (call.args[0] === 'touchmove') { + call.args[1](event = testEvent(52, 200)); + } + }); + + // Should have passed that delta to mct-drag expression + expect(mockScope.$eval).toHaveBeenCalledWith( + testAttrs.mctDrag, + { delta: [10, 140], $event: event } + ); + }); + + it("invokes mctDragUp expression after drag", function () { + var event; + + mockElement.on.mostRecentCall.args[1](testEvent(42, 60)); + + // Find and invoke the touchmove listener + mockBody.on.calls.forEach(function (call) { + if (call.args[0] === 'touchmove') { + call.args[1](testEvent(52, 200)); + } + }); + // Find and invoke the touchmove listener + mockBody.on.calls.forEach(function (call) { + if (call.args[0] === 'touchend') { + call.args[1](event = testEvent(40, 71)); + } + }); + + // Should have passed that delta to mct-drag-up expression + // and that delta should have been relative to the + // initial position + expect(mockScope.$eval).toHaveBeenCalledWith( + testAttrs.mctDragUp, + { delta: [-2, 11], $event: event } + ); + + // Should also have unregistered listeners + expect(mockBody.off).toHaveBeenCalled(); + }); + + }); + + describe("The mct-drag directive in Desktop", function () { + var mockDocument, + mockAgentService, + mockScope, + mockElement, + testAttrs, + mockBody, + mctDrag; + + function testEvent(x, y) { + return { + pageX: x, + pageY: y, + preventDefault: jasmine.createSpy("preventDefault") + }; + } + + beforeEach(function () { + mockDocument = + jasmine.createSpyObj("$document", JQLITE_METHODS); + mockAgentService = + jasmine.createSpyObj("agentService", ["isMobile"]); + mockScope = + jasmine.createSpyObj("$scope", ["$eval", "$apply"]); + mockElement = + jasmine.createSpyObj("element", JQLITE_METHODS); + mockBody = + jasmine.createSpyObj("body", JQLITE_METHODS); + + testAttrs = { + mctDragDown: "starting a drag", + mctDrag: "continuing a drag", + mctDragUp: "ending a drag" + }; + + mockDocument.find.andReturn(mockBody); + mockAgentService.isMobile.andReturn(false); + + mctDrag = new MCTDrag(mockDocument, mockAgentService); mctDrag.link(mockScope, mockElement, testAttrs); }); diff --git a/platform/commonUI/mobile/src/DeviceClassifier.js b/platform/commonUI/mobile/src/DeviceClassifier.js index 6e4529a721..c30dbed896 100644 --- a/platform/commonUI/mobile/src/DeviceClassifier.js +++ b/platform/commonUI/mobile/src/DeviceClassifier.js @@ -44,11 +44,26 @@ define( */ function MobileClassifier(agentService, $document) { var body = $document.find('body'); - Object.keys(DeviceMatchers).forEach(function (key) { + + Object.keys(DeviceMatchers).forEach(function (key, index, array) { if (DeviceMatchers[key](agentService)) { body.addClass(key); } }); + + if (agentService.isMobile()) { + var mediaQuery = window.matchMedia('(orientation: landscape)'); + + mediaQuery.addListener(function (event) { + if (event.matches) { + body.removeClass('portrait'); + body.addClass('landscape'); + } else { + body.removeClass('landscape'); + body.addClass('portrait'); + } + }); + } } return MobileClassifier; diff --git a/platform/features/conductor/core/res/sass/_time-conductor-base.scss b/platform/features/conductor/core/res/sass/_time-conductor-base.scss index 4222936132..0c0c06b475 100644 --- a/platform/features/conductor/core/res/sass/_time-conductor-base.scss +++ b/platform/features/conductor/core/res/sass/_time-conductor-base.scss @@ -145,14 +145,14 @@ margin-right: $interiorMarginSm; } &.start-w { - @include background-image(linear-gradient(270deg, transparent, $wBgColor $ticksBlockerFadeW)); + @include background-image(linear-gradient(270deg, rgba($wBgColor,0), rgba($wBgColor,1) $ticksBlockerFadeW)); padding-right: $ticksBlockerFadeW; .title:before { content: 'Start'; } } &.end-w { - @include background-image(linear-gradient(90deg, transparent, $wBgColor $ticksBlockerFadeW)); + @include background-image(linear-gradient(90deg, rgba($wBgColor,0), rgba($wBgColor,1) $ticksBlockerFadeW)); padding-left: $ticksBlockerFadeW; right: 0; .title:before { diff --git a/platform/features/conductor/core/res/templates/time-conductor.html b/platform/features/conductor/core/res/templates/time-conductor.html index 4ed1eca594..d04acfde65 100644 --- a/platform/features/conductor/core/res/templates/time-conductor.html +++ b/platform/features/conductor/core/res/templates/time-conductor.html @@ -79,12 +79,9 @@ - + - - -