Compare commits

...

215 Commits

Author SHA1 Message Date
Shivam Dave
8072e829ad [Mobile] Comments
Added comments to plot controller
regarding the change in the snapping
to right and mobile adjustment.
2015-09-03 16:30:12 -07:00
Shivam Dave
e866ddb9fd [Mobile] Plot & Gestures
Plot adjusted so that when snapping to the right
the left domain value also moves same amount that
the right domain did. Also Interval between left
and right domains on screen are dyanmically set to
amount zoomed in/out, instead of being defaulted
to 2 minutes. Made small edit to display if the chart
has been manipulated (panned or zoomed) or is updating
live.
2015-09-03 16:15:34 -07:00
Shivam Dave
4fa29d30f5 [Mobile] Gestures
Distance change to differentiate between
pan and pinch increased from 2 to 3.
2015-09-03 11:48:42 -07:00
Shivam Dave
c394151c46 [Mobile] Gestures
Redraw rate adjusted to redraw on
mobile every 15ms instead of 1000ms
(like on desktop). Also added agentservice
to PlotController and MCTChart (bundles and

file.
2015-09-03 11:47:33 -07:00
Shivam Dave
db1b76413c [Mobile] Clean Up
Removed test PlotController functions
which are unused.
2015-09-03 09:53:17 -07:00
Shivam Dave
c8b02d355f [Mobile] Comments
Clarifies what the ratio is for the
distance.
2015-09-03 09:51:12 -07:00
Shivam Dave
7c110ee8af [Mobile] Gestures
Removed plot.html mct-pinch reference
because it was not being used. Also
adjusted MCTPlot comment.
2015-09-03 09:21:10 -07:00
Shivam Dave
49213f550f [Mobile] Comments
Commented on the trackTouchPosition
addition.
2015-09-03 09:08:47 -07:00
Shivam Dave
447ae3f20b [Mobile] Comments
Added comments to the MCTPinch file.
2015-09-02 13:44:17 -07:00
Shivam Dave
7288db1908 [Mobile] Comments
Added comments to the MCTPinch file.
2015-09-02 13:37:17 -07:00
Shivam Dave
908fbdbf73 [Mobile] Clean Up
Changed one line space.
2015-09-02 12:59:44 -07:00
Shivam Dave
052a359738 [Mobile] Comments
Added comments to the MCTPinch file.
2015-09-02 12:58:56 -07:00
Shivam Dave
f9be00a70f [Mobile] Clean Up
Reorganizaed MCTPlot touch
functions to be in suitable order. Also
made code DRYer by removing unnecessary functions
and combining statements that are used once. Also
renamed variables to differentiate similar ones
from one another. Added marks to show where
comments are needed (will be edited in next
commit).
2015-09-02 12:45:52 -07:00
Shivam Dave
d1055f0839 [Mobile] Refactor
Refactored calculateViewport
to use ratio to cacluate the sign of
required zoom in or zoom out, and then
apply that to the ZOOM_AMT. Makes function
DRYer.
2015-09-02 11:23:33 -07:00
Shivam Dave
0b7ab75512 [Mobile] Comments
Added comments to destroy and remaining
MCTPinch functions.
2015-09-02 10:20:49 -07:00
Shivam Dave
9d1841db55 [Mobile] Adjust pan/pinch check
Now check done for pan/pinch using
variables set during start of gesture.
Also added functions to touch amount
checks to make MCTPinch DRYer. Comments
regarding touch functions and added
variables/functions.
2015-09-02 10:18:40 -07:00
Shivam Dave
50d10639e1 [Mobile] Clean Up
Changed variable placement
for amount of distance changed allowed
for a pinch drag.
2015-09-02 09:23:25 -07:00
Shivam Dave
5a9619ce26 [Mobile] Clean Up
Removed unneeded variables passed into
MCTPlot functions.
2015-09-02 09:16:01 -07:00
Shivam Dave
42b7427816 [Mobile] Clean up
Renamed the setDR to be set
Dimensions. Also removed unneeded
calculateDistance function.
2015-09-02 09:14:54 -07:00
Shivam Dave
a1b37b1269 [Mobile] Clean Up
Added comments and cleaned up a bit
of the MCTPinch file.
2015-09-02 09:13:28 -07:00
Shivam Dave
c8ca1deb9b [Mobile] Gestures
Fixed the range of values for
differentiating between pan and
pinch zoom to not assign the +2/-2
value to the variable.
2015-09-01 12:15:48 -07:00
Shivam Dave
5be6e90388 [Mobile] Clean Up
Commented out console calls from gesture
pinch/plot classes. Also allowed pan with
single finger.
2015-09-01 11:53:41 -07:00
Shivam Dave
814b04858a [Mobile] Gestures
MCTPinch adjusted the touch check to help
differentiate between a two finger touch
vs a single singer pan.
2015-09-01 11:45:11 -07:00
Shivam Dave
aedbd3bd9b [Mobile] Gestures
ZOOM_AMT set back to original
0.02, because .025 made zoom out
too fast.
2015-09-01 10:45:02 -07:00
Shivam Dave
aa4dbf7062 [Mobile] Gestures
Ratio used to check if
zoom should be in or out now
divides lastDistance/distance
instead of firstDistance/distance.
Therefore by comparing last distance,
user is able to zoom in and out on
same pinch without removing fingers.
2015-09-01 10:24:32 -07:00
Shivam Dave
5b95574673 [Mobile] Gestures
Slight adjustment to the ZOOM_AMT,
increased by .005 from .02 to .025.
2015-09-01 10:22:02 -07:00
Shivam Dave
2295be5e35 [Mobile] Gestures
Set the range of difference allowed between
the last distance and current distance to
differenciate panning and zooming. If
lastDistance - 2 <= currentDistance <= lastDistance + 2
than panning occurs, otherwise user is zooming.
BUG: The auto snap to right side of chart causes the
chart to resize narrower overtime and as user BOTH
zooms and pans more.
2015-09-01 10:17:53 -07:00
Shivam Dave
0ac6caa823 [Mobile] Gestures
Added a zoom amount variable
that is set at top of MCTPlot.
Sets the amount of zoom multiplier.
2015-09-01 10:14:51 -07:00
Shivam Dave
5e1dd04e6d [Mobile] Pinch & Pan
Adjusted Pinch to check if
distance between 2 fingers
(rounded to whole number) is equal to
last distance or first distance, if this
is true, than will pan otherwise do
pinch zoom.
2015-08-31 16:25:44 -07:00
Shivam Dave
29df378851 [Mobile] Gestures
Removed firstTouchPan and use
firstTouch for both the pinch and the
single touch pan.
2015-08-31 16:22:43 -07:00
Shivam Dave
8511c957a0 [Mobile] Gestures
Adjusted the 0.03 'multiplier'
from 0.01, to allow faster zooming in
and out.
2015-08-31 15:48:11 -07:00
Shivam Dave
f4efc79539 [Mobile] Clean up
Removed call to console.
2015-08-31 15:47:19 -07:00
Shivam Dave
3926d6f617 [Mobile] Gesture
Zooms in at 0.01 amount (like last commit)
however the pinch's midpoint is the center
point at which the zoom focuses on.
2015-08-31 15:33:33 -07:00
Shivam Dave
d65e0f820f [Mobile] Gestures
Currently zooms into center by narrowing each
dimension by 0.01
2015-08-31 14:47:02 -07:00
Shivam Dave
24fe419be4 [Mobile] Gestures
Slight clean up to MCTPinch.
2015-08-31 13:01:15 -07:00
Shivam Dave
3e2c3f913b [Mobile] Gesture Check
Commented out panand trackes current 2
touches on pinch.
2015-08-28 16:48:54 -07:00
Shivam Dave
a45b09277e [Mobile} Pan/Pinch
Cleaned up the variables.
2015-08-28 16:01:00 -07:00
Shivam Dave
bdf3e4d8a3 [Mobile] Pan/Pinch
On destoying the scope of
MCTPinch, all the listeners for
touch events on the element are
destroyed.
2015-08-28 15:39:16 -07:00
Shivam Dave
e4a2904213 [Mobile] Pan Gesture
Added pan gesture functionality
with one finger to MCTPlot.
2015-08-28 15:23:19 -07:00
Shivam Dave
f1d4e36c02 [Mobile] Gestures
Added an endTouch/Zoom to the
MCTPlot to mark when the user
has canceled/ended their touch
event.
2015-08-28 15:22:15 -07:00
Shivam Dave
b3792c21be [Mobile] Gestures
Adjusted MCTPinch names to work
for both pan and pinch.
2015-08-28 15:20:46 -07:00
Shivam Dave
1fbbf355f4 [Mobile Gestures] Pan
Adds pan gesture to plots. Sets up the
zoom gesture addition. Also the back button
is visible on desktop versions.
2015-08-20 11:26:09 -07:00
Shivam Dave
9fec73da14 Merge remote-tracking branch 'upstream/plot-vee-two' into mobile_gestures_1 2015-08-17 13:20:02 -07:00
Shivam Dave
23048f0df9 [Mobile Gestures] Comments
Added comments to pinch functions.
2015-08-17 13:15:46 -07:00
Shivam Dave
dfe3409a98 [Mobile, Gestures] Pinch
Split the pinch gesture into start,
change, and end/cancel. Each of those
are read in and then they emit through
the scope to functions in the controller.
2015-08-17 13:12:53 -07:00
Shivam Dave
5c3fe78bd5 [Mobile, Gestures] Pinch
Moved MCTPinch directive into
plot-reborn. Now emits on pinch action
the event to the controller. Edited plot.html
to clean up and edited mct-plot.html to
include mct-pinch. DrawLoader adjusted to
allow  and prevent error.
2015-08-17 12:51:33 -07:00
Pete Richards
eb69e02ce3 [Plot] Reset telemetry objects on change 2015-08-17 12:39:38 -07:00
Shivam Dave
17e2da2d2c Merge remote-tracking branch 'upstream/plot-vee-two' into mobile_gestures_1 2015-08-17 10:53:54 -07:00
Shivam Dave
03db1b3623 Merge remote-tracking branch 'upstream/master' into mobile_3 2015-08-17 10:51:28 -07:00
Shivam Dave
5c23daa5ff [Mobile, Gestures] Pinch
Pinch directive commited with removal
of gestures. Added connection to controller
and plot application on html file.
2015-08-17 10:49:11 -07:00
Pete Richards
056b3f61ce [Style] JSLint Compliance 2015-08-14 11:54:46 -07:00
Pete Richards
a0dc3da8fb [Plot] Use ColorService for plot colors 2015-08-13 16:07:08 -07:00
Pete Richards
48f345a46b [Service] ColorPalette is now ColorService 2015-08-13 16:06:26 -07:00
Shivam Dave
2cf7f6794c Merge remote-tracking branch 'upstream/master' into mobile_3 2015-08-13 09:14:28 -07:00
Pete Richards
889a5c6ea9 Allow duplicates in repeats, use proper labels 2015-08-12 16:50:51 -07:00
Pete Richards
5502009127 Reasonable defaults for directive scope 2015-08-12 16:50:09 -07:00
Pete Richards
cb41be7922 Plot uses ColorPalette to allocate colors 2015-08-12 16:27:28 -07:00
Shivam Dave
2997f2a261 [Mobile, Gestures] Removed Gesutres
Removed gesture info from bundles,
switching to using directives for
pinch.
2015-08-12 16:22:04 -07:00
Pete Richards
52b8720d37 ColorPalette dispenses colors. 2015-08-12 16:17:20 -07:00
Pete Richards
bb8c8a75ab MCTChart preserves precision of plot values 2015-08-12 13:59:32 -07:00
Shivam Dave
d10c56f732 Merge remote-tracking branch 'upstream/master' into mobile_3 2015-08-12 09:27:02 -07:00
Shivam Dave
1f7d0427b7 [Mobile, Gestures] Clean Up
Moved one file, push/pan still
applied to whole pane.
2015-08-11 12:13:43 -07:00
Shivam Dave
caf1e3aea9 [Mobile, Gestures] Tests
Adjusted tests to call to correct
firedGesture.
2015-08-11 10:57:52 -07:00
Shivam Dave
3031579a62 [Mobile] Gestures
Started gesture implementation for
representation panes. Currently added Pan
and Pinch Gesture js, where the PanGesture
tracks single finger movement. PinchGesture
tracks the distance between two fingers. Also
added test spec files that test without error
but are incomplete. Current issue is that
pinch and pan gestures are applied to the entire
right pane, which includes header. Need to target
only representation of the right pane.
2015-08-10 11:31:33 -07:00
Shivam Dave
00aa7ce0c2 [Mobile, Gestures] Pinch/Pan
Made unbind call more DRY.
2015-08-07 14:52:23 -07:00
Shivam Dave
cac97401c6 [Mobile, Gestures] Pan/Pinch
Added Destroy return function that
.off all touch events on elements.
And unbinds touch events from element.
2015-08-07 14:26:23 -07:00
Shivam Dave
7b371327e6 [Mobile, Gestures] Pan
Added pan file which is based on
PinchGesture. Also made PinchGesture more
DRY. PanGesture, like PinchGesture only
logs the pan coordinates on touch moving.
Added check to pinch and pan to disallow those
gestures in folder representations.
2015-08-07 14:16:32 -07:00
Shivam Dave
113d1c909f [Mobile, Gestures] Pinch
Pinch gesture being implemented.
Currently tracks two touchChanges
that track location and find distance
between them. Logs the distances currently.
2015-08-07 12:20:57 -07:00
Shivam Dave
7ca15a9de2 [Mobile] Representation
Edited grid item to center
shared button.
2015-08-06 14:11:59 -07:00
Shivam Dave
dcd7d61c9a [Mobile] Tests
Completed ContextMenu and InfoButton
Gesture tests where elements/body
touch events occur.
2015-08-06 13:43:56 -07:00
Shivam Dave
0a39984c4f [Mobile] Clean Up
Fixed InfoService having 0 in
wrong spot. Also correctly compared
the UserAgent device to iPhone for
isMobile function in AgentService.
2015-08-05 12:26:09 -07:00
Shivam Dave
0b635afcf7 [Mobile] Tests
ContextMenu and InfoButton Gesture
tests remain.
2015-08-05 12:14:16 -07:00
Shivam Dave
f46a0853b9 [Mobile] Tests
Removed mockMenu from ContextMenuGestureSpec.
2015-08-04 16:58:37 -07:00
Shivam Dave
6b65ae77e7 [Mobile] Tests
Completed tests for AgentService,
InfoService, and ContextMenuAction.
ContextMenu and InfoButton Gesture
tests remain. Also resized info button
icon.
2015-08-04 16:48:41 -07:00
Shivam Dave
66408eeec8 [Mobile] Gestures
Now to dismiss bubble, touch anywhere
the touch will not fire other gestures
(such as the pressing of another object).
2015-08-04 13:41:48 -07:00
Shivam Dave
3d524d7572 [Mobile] AgentService
Replaced name queryService with agentService.
2015-08-04 10:11:25 -07:00
Shivam Dave
9b922913a0 [Mobile] Gestures
Added styling to back and selection
arrow (tree). Also increased the space
allowed for selection arrow on tree item.
Info Button created on grid items for mobile.
Info bubble appears on tablet like desktop.
Also on mobile, info bubble fits to width.
New QueryService that returns if on iPhone.
Also formatted dialog box so that their is no
margin and takes up fullscreen on mobile.
2015-08-04 09:59:08 -07:00
Shivam Dave
560a2e035e [Mobile] Info Button
Added info button to grid/list items
on mobile. When the button is pressed,
info bubble appears for 750ms or the
same infobutton is pressed to dismiss
immediately.
2015-07-31 11:13:52 -07:00
Shivam Dave
eca52a8ca6 Merge remote-tracking branch 'upstream/master' into mobile_3 2015-07-31 09:09:31 -07:00
Shivam Dave
25e8bb44d2 [Mobile] Item Height
Adjusted item height in
folder/layout list to be
automatically same as the
list object, not flowing over.
Applied to both phones and tablets.
2015-07-30 14:10:43 -07:00
Shivam Dave
85658d3d1f [Mobile] Tests
Removed tests causing incomplete
build.
2015-07-30 13:33:59 -07:00
Shivam Dave
ddce0f371d [Mobile] Test
Removed extra mockEvent from test.
2015-07-30 13:32:24 -07:00
Shivam Dave
495cd06ed5 [Mobile] Tests
adjusted test to fill empty
functions.
2015-07-30 13:30:03 -07:00
Shivam Dave
1624866656 [Mobile/Bug] RemoveAction
When removing object you have
openned, now compares the currentObj
id with the removed obj id, resulting
in navigating to parent if they are the
same.
2015-07-30 13:27:56 -07:00
Shivam Dave
2d1aa65d63 [Mobile] Test
BrowseController test adjusted to
repeat less code.
2015-07-30 12:50:39 -07:00
Shivam Dave
c333a2e70a [Mobile] Test
Repeat of test variable deleted.
2015-07-29 16:31:38 -07:00
Shivam Dave
906354764b [Mobile] Tests
Has way to make isMobile call
true or false for mobile/nonmobile
devices.
2015-07-29 15:06:39 -07:00
Shivam Dave
12ec293f3d [Mobile] Tests
Changed BrowseController and RemoveActionSpec to account
for grandparent and navigation usage. Also changed
RemoveAction variable name.
2015-07-29 13:57:11 -07:00
Shivam Dave
bdf8b4d3f1 [Mobile] Test for Back Arrow
Added tests for the backarrow and
when it appears/disappears.
2015-07-29 13:22:47 -07:00
Shivam Dave
6e60088b11 [Mobile] RemoveAction
Removed console and added
navigationService (mock) to the
spec version.
2015-07-29 11:58:53 -07:00
Shivam Dave
97bf530b1d [Mobile] BackArrow
Removed the BackArrow console log
that was getting called in the
BrowseController.
2015-07-29 11:41:10 -07:00
Shivam Dave
18348476c6 [Mobile] RemoveAction Tweak
If you remove an object you are
currently within/opened, then on
removal of it you navigate to the
parent of whatever you removed.
2015-07-29 11:38:47 -07:00
Shivam Dave
7e35e55f0b [Mobile] Hide Back Button
When you are at the highest level the
back button fades out and is unclickable.
When you are able to go up a level the
back button appears/fades in and is
pressable. Also removed the object type
name from the header.
2015-07-29 11:13:09 -07:00
Shivam Dave
28a2a5b92a [Mobile] Tweaks to layout
Removed the user-select option
for the context menu and bottom bar
on mobile. Also edited the folder
grid item so that its icon rep
size is not overly large.
2015-07-29 10:39:17 -07:00
Shivam Dave
d262520594 [Mobile] Tree menu Open
Tree menu select arrow button's width
is now size of full button. Prior to this
the pressable area was less and therefore
less responsive.
2015-07-29 10:25:09 -07:00
Shivam Dave
7cc14a195b [Mobile] Tests/Header
Removes back arrow on desktops.
Also added queryService to tests
for the context menu action and
gesture.
2015-07-29 10:00:03 -07:00
Shivam Dave
84b9e4d781 [Mobile] Context Menu
Context menu next to object header
now dismisses when touching away
from it. Also, when long touching
an object, the context menu appears.
Set on 500ms timeout.
2015-07-28 17:09:15 -07:00
Shivam Dave
356fa73c91 [Mobile] Tests
Test created for backArrow
that spies on all objects
used to find parent.
2015-07-28 15:55:22 -07:00
Shivam Dave
a073ef69ac [Mobile] Back Arrow
Shifted Back Arrow down to
align with header.
2015-07-28 15:15:42 -07:00
Shivam Dave
3c6c420023 [Mobile] Back Arrow
Back Arrow implemented
by getting parent and then
navigating to it.
2015-07-28 15:08:14 -07:00
Shivam Dave
2a4943f584 [Mobile] Console
Removed call to console so
mvn clean install would compile.
2015-07-28 10:58:22 -07:00
Shivam Dave
e32403a75f [Mobile] Clean-Up
Cleaned the unused code for the
backArrow and long touch gestures.
Commented out functions for later use
Currently shows the back arrow, however,
only will print to console on press.
Edited tests where mobile checks were breaking
and fixed.
2015-07-28 10:56:29 -07:00
Shivam Dave
b0c42c12b7 [Mobile] Back Arrow
Changes URL correctly that
is printed to the console. Is the
url to up one level of objects.
However not navigating to that
object.
2015-07-27 17:01:30 -07:00
Shivam Dave
621ccc25ec [Mobile] Back Arrow HTML
Created HTMl for back arrow,
next neew to hook up a click.
2015-07-27 15:31:47 -07:00
Shivam Dave
617df739ee [Mobile] persistence
Removed elasticsearch.
2015-07-27 15:26:09 -07:00
Shivam Dave
6e43a92191 [Mobile] Merge
Fix Conflicts.
2015-07-27 15:21:59 -07:00
Shivam Dave
a9418fd2c7 Merge remote-tracking branch 'upstream/master' 2015-07-27 11:32:41 -07:00
Shivam Dave
1d7a0fa48d [Mobile] Removed InfoGesture
Commented out infogesture.
2015-07-27 11:30:29 -07:00
Shivam Dave
30c530178a [Mobile] No ContextMenu
Removed context menu code
started to be used for the
long hold gesture.
2015-07-27 11:01:03 -07:00
Shivam Dave
3d0795cde3 [Mobile] Starting Context
Added check to make sure
user is touching only one object.
Started contextmenugesture to be
long touch, however currently long
touch is still infogesture.
2015-07-27 10:20:08 -07:00
Shivam Dave
c85a3787c0 [Mobile] User-Select
Edited user-select used in
panes' layout to only
happen on phones and tablets
(just to be safe).
2015-07-24 16:46:45 -07:00
Shivam Dave
066258ab83 [Mobile] User-Select
Removes the copy/define
mobile safari menu that
appears during some touch events.
Only apply to left and right panes.
2015-07-24 16:19:15 -07:00
Shivam Dave
ddc2295ec3 [Mobile] Touch Hold Gesture
Rough touch hold gesture added
to the info gesture. Currently
if you hold on an item (that you
would normally hover over) for
500ms, you get the info gesture pop
up.
2015-07-24 16:02:06 -07:00
Shivam Dave
011e6fc512 [Mobile] Clean Up
Moved Mobile check in InfoGesture to
call on mouseEnter.
2015-07-24 15:27:33 -07:00
Shivam Dave
91bd58215a [Mobile] Size Adjustment
Moved hamburger icon slightly up
using the padding instead of
margin.
2015-07-24 12:38:01 -07:00
Shivam Dave
b37ee19fbc [Mobile] Size Adjustment
Adjusted indentation size
on the tree. Also change size of the
hamburger icon to match the
object icon and moved it slightly
down.
2015-07-24 12:35:19 -07:00
Shivam Dave
2355d354b3 [Mobile] Items List
Flushes items left and
vertically centers the
title/details. Also cleaned
up the items classes in sass
files.
2015-07-24 11:46:58 -07:00
Shivam Dave
200c6e49fc [Mobile] Test
QueryService (mock) added to the
ContextMenuGestureSpec to account
for isMobile call that allows/
disallows use of contextmenu
gesture.
2015-07-23 16:55:45 -07:00
Shivam Dave
a89f9eed42 [Mobile] Grid List/Gestures
Context menu only shown with contextmenu
click on desktops (non-mobile devices). Also
edited items list in a folder's representation
to show the icon on the left side, with text
centered horizontally (only mobile).
2015-07-23 16:47:57 -07:00
Shivam Dave
7993e4c03f [Mobile] Gestures
Removed the hover coloring on
the tree menu on mobile by changing
original** scss code. Also added
check in ContextMenuGesture that
will only allow context menu to appear
in non-mobile browser.
2015-07-23 15:01:14 -07:00
Shivam Dave
b592b89dc8 [Mobile] Clean Up
Removed unnecessary transitions.:
2015-07-23 14:15:01 -07:00
Shivam Dave
d115166dde [Mobile] Comments
Added comments and removed
unwanted spec test code for
BrowseController.
2015-07-23 13:48:21 -07:00
Shivam Dave
d176f9f811 [Mobile] Test
Fixed BrowseControllerSpec.js to
account for the .treeslide
call and added a new test for thatasds
2015-07-23 13:46:46 -07:00
Shivam Dave
143e3eeb6c [Mobile] CleanUp/Tests
Added tests inside spec files
for the QueryService, TreeNodeController,
and InfoGesture. Also cleaned up the
tree so that padding is used between
buttons instead of margins.
2015-07-23 13:19:58 -07:00
Shivam Dave
50ce800c2a Merge branch 'master' of https://github.com/shivamndave/openmctweb 2015-07-23 09:51:33 -07:00
Shivam Dave
1a1eecb4c3 Merge remote-tracking branch 'upstream/master' 2015-07-23 09:51:10 -07:00
Shivam Dave
b3bc8b6876 [Mobile[ Tests
Added jasmine test for

QUerySerivce and adjusted
the InfoGestureSpec to
account for use of
QueryService.
2015-07-23 09:28:36 -07:00
Shivam Dave
1f7ba70ad7 [Mobile] Scroll Bug
Removed scrollbar that appears in landscape
mode in tree menu.
2015-07-22 15:21:34 -07:00
Shivam Dave
7aba3b6672 [Mobile] Clean Up
Removed gap below bottom bar. Moved
around constants for the resizing
of the tree. Also added comments in
layout and reformatted that slightly.
2015-07-22 12:53:49 -07:00
Shivam Dave
926b3d075c [Mobile] Clean Up
Cleaned up scss files. Removed
repeated statements and added
comments. Also commented js files
like QueryService and InfoGesture.
2015-07-22 10:25:21 -07:00
Shivam Dave
827cb27f28 [Mobile] Menu
Added margin to top of tree list items.
Also removed hovering Info coming
up on mobile devices.
2015-07-21 16:19:59 -07:00
Shivam Dave
0842f464db [Mobile] Menu Adjustment
Makes highlight go all the way to right.
Also makes the arrow be absolute on the
right side, making it aligned to right.
2015-07-21 14:29:13 -07:00
Shivam Dave
56e51ea32a [Mobile] Reformat of menu
Reformats menu to move the
arrow to the right and now
that is what selects an object.
Pressing the actual menu item will
enact the dropdown menu. This
only happens on mobile platforms.
2015-07-21 13:29:45 -07:00
Shivam Dave
dcdafbaebf [Mobile] Fix Shift
Shifting occurring during transition
fixed by making transition backface-
visibility hidden during the
transition.
2015-07-20 10:25:27 -07:00
Shivam Dave
f98915cddd [Mobile] Comments
Added comments to the mixin list.
2015-07-20 09:51:37 -07:00
Shivam Dave
4e6c307684 [Mobile] Transition
Adjusts transition time on fade.
2015-07-20 09:48:12 -07:00
Shivam Dave
ce6d74390e [Mobile] Clean-Up
Removed unnecessary classes. Also added
comments and adjusted menu sizes.
2015-07-20 09:39:06 -07:00
Shivam Dave
6e406fd060 [Mobile] Right Pane sets
Right pane sets the size of itself,
causing the left pane to re-adjust
to fit the screen based on it. Also
transitions work on the slide and the
fade in.
2015-07-20 09:16:28 -07:00
Shivam Dave
2614427e0e [Mobile] Fix
Fixed to open menu fully.
2015-07-17 14:32:33 -07:00
Shivam Dave
272c6bca97 [Mobile] Create Menu
Create menu's is specified/overwritten
with 1000% (change) to fit on mobile).
Also gets rid of the right bar in that view.
2015-07-17 10:50:02 -07:00
Shivam Dave
0d7387080d [Mobile] Create Menu
Create menu text has ellipsis
attribute now, so if text is cut off
it will have a '...' appended to it.
Also added comments to mixins.
2015-07-17 10:28:19 -07:00
Shivam Dave
1e2e20b145 [Mobile] Comments
Added comments to the mixins.
2015-07-17 09:04:39 -07:00
Shivam Dave
488829a20c [Mobile] Header
Removed type from header
along with the right side buttons.
2015-07-16 16:13:58 -07:00
Shivam Dave
85c7a36e25 [Mobile] Cleaned up
Set the width of the create menu
text/components to fit the menu
however it gets cuttoff sometimes.
Next steps are to Clean up screen,
change the create menu to fit the left side,
and fix bottom space.
2015-07-16 15:21:17 -07:00
Shivam Dave
d99b4d75d8 [Mobile] Fix
Fixed the desktop version breaking.
CUrrent issue is hte menu is getting cut off.
2015-07-16 14:07:25 -07:00
Shivam Dave
15a88967d0 [Mobile] Transition/Create Fix
Fix the create button to work and
also transition well. Added transition mixin
to stay DRY.
2015-07-16 13:22:07 -07:00
Shivam Dave
6e6fbe0d65 [Mobile] Transitions
Made transitions properly work for
create button.
2015-07-16 12:54:10 -07:00
Shivam Dave
180e5f14ae [Mobile] Cleaned up
Made pane sass code more DRY by
using the phoneandtablet mixin
on repeated conditions.
2015-07-16 12:25:06 -07:00
Shivam Dave
e9314898d2 [Mobile] Portrait & Landsc.
Specifies amounts based on phone and tablet's
orientation. Not tested for the actual device,
but emulator. Also currently makes the create
button appear/disappear instead of smoothly sliding.
2015-07-16 11:50:55 -07:00
Shivam Dave
ce75d19480 [Mobile] Desktop
Cleans up the _layout by making the different
pane sizes device specific. Also adds a new
sass class just for desktop versions.
2015-07-16 10:44:20 -07:00
Shivam Dave
a9dd1f9828 [Mobile] Transistions
Cleaned up and added transitions.
2015-07-15 16:57:36 -07:00
Shivam Dave
4b5540830b [Mobile] Slide menu
Rouch menu using important to
overwrite splitter setting of
amounts. Also has default values
for now for all devices.
2015-07-15 16:49:16 -07:00
Shivam Dave
ee35976c92 [Mobile] Tree Mobile
Added mobile/_tree.scss and edited
normal tree.scss to accomodate for
future sass that adjusts the tree
menu.
2015-07-15 13:30:06 -07:00
Shivam Dave
54b6cd1100 [Mobile] Debug
Added debug statement to print
to console.
2015-07-15 13:28:42 -07:00
Shivam Dave
0f89e98a71 [Mobile] Clean up
Cleaned up layout and added phone only hider.
Also added tree.scss file, where all tree
node classes will be placed.
2015-07-14 14:14:12 -07:00
Shivam Dave
6f07a21bb8 [Mobile] Clean-up
Cleaned up scss and also, the
edit/new tab/full screen buttons are
hidden in mobile, temporarily.
2015-07-14 13:10:28 -07:00
Shivam Dave
f3678d9d52 Merge remote-tracking branch 'origin' into mobile_1 2015-07-14 13:08:54 -07:00
Shivam Dave
9a7bbd92bd [Mobile] Cleaned up
Cleaned up the transistion css to
be more DRY.
2015-07-13 17:04:14 -07:00
Shivam Dave
edcafc5835 [Mobile] Remove Bar
Remove the splitter bar on mobile
and tablets.
2015-07-13 13:56:44 -07:00
Shivam Dave
7d09df9a85 [Mobile] Constants
Re-edited media query constants
to be cleaner and consistent.
2015-07-13 13:11:27 -07:00
Shivam Dave
b00eee00fc [Mobile] Redefine
Renames variables to be clearer.
Breaks up constants into parts to be
cleaners and straightforward. Also
removed the ratio.
2015-07-13 13:02:57 -07:00
Shivam Dave
c0d83f9395 [Mobile] Format
Reformatted the rwd media
query rules.
2015-07-13 12:39:09 -07:00
Shivam Dave
be757066f5 [Mobile] Desktop adjusted
Adjusted the desktop to accomodate browser
orientation changes. Done so by forgoing
checking the orientation because the
actual device can be in landscape, but it
reads orientation based on the viewport.
2015-07-13 11:18:51 -07:00
Shivam Dave
885433390e [Mobile] Fix for emu and act
Adds 2 landscape conditions for tablets and
phones to check if they are in landscape, in
the actual tablet, or in an emulate of the tablet,
then it displays.
2015-07-13 10:32:58 -07:00
Shivam Dave
687f810475 [Mobile] Constants
Fixed width constant to work for laptop.
2015-07-13 10:23:28 -07:00
Shivam Dave
137a60f510 [Mobile] Constants
Fixed constants to work for laptop.
2015-07-13 10:16:52 -07:00
Dave
46d5a1431f [Mobile] Added Constants
Rixed mis-initialized desktop
constant
2015-07-13 09:24:01 -07:00
Dave
404d02ec23 [Mobile] Added Constants
Re-edited constants to set min
ones for the desktop screen, that
is based on the device size.
2015-07-13 09:17:59 -07:00
Shivam Dave
eec955317a revert back to
4d9dc3624b
2015-07-10 12:47:00 -07:00
Dave
67890a7298 [Mobile] Test 2015-07-10 12:38:04 -07:00
Dave
dd457f26c6 [Mobile] Device
Added max width to tablet check.
2015-07-10 12:32:34 -07:00
Dave
85c6bda5c9 [Mobile] Device
Adjusted Tablet slide Constant.
2015-07-10 12:21:13 -07:00
Dave
b7b5f87002 [Mobile] Device
Adjusted Comp Constant.
2015-07-10 12:16:43 -07:00
Dave
b0c5d807e7 [Mobile] Device
Removes splits desktop
settings into 2, one
for landscape and another
for portrait.
2015-07-10 11:51:56 -07:00
Dave
4d4776e0ef [Mobile] Device
Removes desktop mixin settings
that do not use device width and
height.
2015-07-10 11:40:57 -07:00
Dave
61e1aeb1d8 [Mobile] Device
Removes desktop mixin settings
that do not use device width and
height.
2015-07-10 11:40:14 -07:00
Dave
9caa603a65 [Mobile] Device
Removes desktop mixin settings
that do not use device width and
height.
2015-07-10 11:36:45 -07:00
Dave
5c99e469d5 [Mobile] Device Change
Now instead of min-width, max-width,
... etc, uses the device-width/height.
This allows the devices to use the slide
menu while the browser on a desktop
consistently stays as desktop mode, no
matter if it is resized. As a result of this
the rwd is clear on phones/tablets, but not if
user resizes browser super small.
2015-07-10 11:29:30 -07:00
Dave
4d9dc3624b [Mobile] Items
Item icons disappear now on
tablets and mobile devices.
Adjusted _items.scss to adjust the
icon class display for phones and
tablets.
2015-07-10 11:12:09 -07:00
Dave
d3ae4b729f [Mobile] More consistent
More consistent when moving from
landscape to portrait and
vice-versa on devices. However
still encountering issue with
the browser being resized.
2015-07-10 10:56:48 -07:00
Dave
30bed434fe [Mobile] Moved variables
Moved variables used for amount of
side bar and slide amount into the
mobile/_constants.scss file.
2015-07-10 09:02:46 -07:00
Dave
3e4ae4d38d [Mobile]
Reverted changes to original controller file.
2015-07-09 15:38:53 -07:00
Dave
7414275a85 [Mobile]
Reverted changes to original scss file.
2015-07-09 15:37:03 -07:00
Dave
fcb0033864 [Mobile]
Reverted changes to css file.
2015-07-09 15:32:41 -07:00
Dave
f079471a18 [Mobile]
Reverted changes to scss file.
2015-07-09 15:31:35 -07:00
Dave
1fb1174c0a [Mobile] Clean-Up
Removed unused scss constant
.
2015-07-09 15:19:29 -07:00
Dave
635e1eda69 [Mobile] Clean-Up
Removed unused menu button and
cleaned up treeCl to be treeClass.
2015-07-09 15:14:36 -07:00
Dave
40d53f941f [Mobile] TreeMenuController
Removed the TreeMenuController.js file
and from the bundle. What this achieves
is already done in BrowseController.js
2015-07-09 14:46:36 -07:00
Dave
684a0e88a2 [Mobile] Constants
Added constants to the
mobile one with device
height.
2015-07-09 14:26:02 -07:00
Dave
30a4f15330 [Mobile] Adjusted
Adjusted the _layout.scss to
have a function that makes
something disappear on phone
and tablet.
2015-07-09 14:11:51 -07:00
Dave
dfd08000f1 [Mobile] Adjust
Adjusted the tablet amount
that the slide occurs.
2015-07-09 13:42:07 -07:00
Dave
82c8d26264 [Mobile]
Now does not display
the icon for the slide menu
on desktops.
2015-07-09 11:16:41 -07:00
Dave
bd236e1cb1 [Mobile] Icon
Added menu/hamburger icon.
2015-07-09 11:06:25 -07:00
Dave
e47a36e799 [Mobile] Simplified
treeSlide now uses one line that
sets it to true or false simply
like a switch. So not matter what
it will either slide or not.
2015-07-09 10:55:52 -07:00
Dave
30efec0090 [Mobile] Angular
Replaced document usage with
angular calls that change the ternary
op to flip the slide.
2015-07-09 10:53:03 -07:00
Dave
b9371ea03d [Mobile] Moved Button
Button moved to the Browse.html
and BrowseController handles the
tree slide.
2015-07-09 10:28:45 -07:00
Dave
7974f33781 [Mobile] Phone
Adjusted to differentiate
phones and tablets.
2015-07-08 16:28:40 -07:00
Dave
cdcaedc8dd [Mobile] Added transistions
Transistions added, however still using
document.getElementById.
2015-07-08 15:57:08 -07:00
Dave
07ef4dfe8a [Mobile] Menu Slide
Menu slides, but not transition
css slides out on click. Currently
uses document, which needs to be
replaced with angular version using
 and/or  and/or
ng-class and/or ng-click.
2015-07-08 14:27:59 -07:00
Dave
342be0822f [Mobile] Gen css 2015-07-08 12:17:19 -07:00
Dave
5c56484889 [Mobile] Main scss added
Added the mobile files as imports
to the main scss files that
generate as css files.
2015-07-08 12:14:40 -07:00
Dave
2b4162c0be [Mobile] Reorganize
Reorganized the sass files. To incorporate, new
mobile directory, which holds all the mobile
sass code.
2015-07-08 12:11:48 -07:00
Dave
3704d64560 [Mobile] Push to show current 2015-07-08 11:08:31 -07:00
Dave
24fae72492 [Mobile] Left tree
Attempt to resize left
tree menu when changing device.
Currently does not move the splitter
bar.
2015-07-07 16:46:32 -07:00
Dave
79fb6eabd9 [Mobile] Menu Button
Menu button added to the
bundle and as a file modelled
after the action button.
2015-07-07 16:28:34 -07:00
Dave
1ddb00c8d6 [Mobile] Resize
Resized the height of each
item in grid based on new
tablet/phone widths.
2015-07-07 14:01:57 -07:00
Dave
8a0b77ec5c [Mobile] Folder View
Folder representation now
will be a list.
2015-07-07 13:02:40 -07:00
Shivam Dave
2fc447e16f [Mobile] Comments
Added comments and reverted the
grid back to normal.
2015-07-07 10:15:25 -07:00
Shivam Dave
d828bf59f9 [Mobile] Constants/Etc
Added constants for media queries.
in _constants.scss. Also, now on tablet,
zoom is disabled.
2015-07-07 09:58:22 -07:00
Shivam Dave
d8806f14aa [Mobile] Set viewport
Viewport has been set in
index.html. Then what was
implemented prior to this
(rem-display and browser-manage)
was commented out.
2015-07-07 09:08:16 -07:00
Shivam Dave
0c6a9ca857 [Mobile] Styles
Added new style to set the width
of the tree.
2015-07-06 13:15:38 -07:00
Shivam Dave
07c907b315 Merge remote-tracking branch 'upstream/master' 2015-07-02 13:14:27 -07:00
Dave
d343d38037 Merge remote-tracking branch 'upstream/master' 2015-07-01 13:30:08 -07:00
Shivam Dave
73241efdc8 [Fix] Fixes bundle
Changes the persistance to the example
version.
2015-06-30 13:20:46 -07:00
larkin
b40494ac95 plot-reborn WIP 2015-06-12 13:53:53 -07:00
78 changed files with 4550 additions and 242 deletions

View File

@@ -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",

View File

@@ -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"

View File

@@ -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": [

View 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-->
<span ng-controller="BrowseController"
ng-click='backArrow()'
ng-class="checkRoot(); atRoot ? 'mobile-back-hide' : 'mobile-back-unhide'">
<a class='type-icon icon ui-symbol'>{</a>
</span>

View File

@@ -25,8 +25,8 @@
<mct-representation key="'object-header'" mct-object="domainObject">
</mct-representation>
</div>
<div class="btn-bar right abs">
<!-- Temporarily, on mobile, the button bar is hidden-->
<div class="btn-bar right abs mobile-hide">
<mct-representation key="'action-group'"
mct-object="domainObject"
parameters="{ category: 'view-control' }">

View File

@@ -19,29 +19,31 @@
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 content="jquery-wrapper" 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 tree-holder abs'>
<div class='split-pane-component treeview pane mobile-pane left-menu desktop-browse'>
<div class='holder tree-holder abs mobile-tree-holder'>
<mct-representation key="'tree'"
mct-object="domainObject"
ng-model="treeModel">
</mct-representation>
</div>
</div>
<mct-splitter></mct-splitter>
<div class='split-pane-component items pane'>
<div class='holder abs' id='content-area'>
<mct-representation mct-object="navigatedObject" key="'browse-object'">
<mct-representation key="'create-button'" mct-object="navigatedObject">
</mct-representation>
</div>
</div>
<mct-splitter class="mobile-hide"></mct-splitter>
<div class='split-pane-component items pane mobile-pane right-repr'>
<div class='holder abs' id='content-area'>
<mct-representation mct-object="navigatedObject" key="'browse-object'">
</mct-representation>
</div>
<div class="left s-very-subtle key-properties ui-symbol mobile-menu-icon button-pos"
ng-click="treeSlide()">m</div>
</div>
</mct-split-pane>
</div>
<mct-include key="'bottombar'"></mct-include>

View File

@@ -19,11 +19,12 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class='object-header'>
<div class='object-header object-header-mobile'>
<span class="label s-label">
<mct-representation key="'back-arrow'"></mct-representation>
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
<span class='type-name'>{{type.getName()}}</span>
<span class='type-name mobile-important-hide'>{{type.getName()}}</span>
<span class='title-label'>{{model.name}}</span>
<mct-representation key="'menu-arrow'" mct-object='domainObject'></mct-representation>
</span>

View File

@@ -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>

View File

@@ -20,13 +20,13 @@
at runtime from the About dialog for additional information.
-->
<!-- For selected, add class 'selected' to outer div -->
<div class='item grid-item' ng-click='action.perform("navigate")'>
<div class="contents abs">
<div class='item grid-item'>
<div class="contents abs mobile-grid-nav" ng-click='action.perform("navigate")'>
<div class='top-bar bar abs'>
<div class='left abs'>
<mct-include key="_checkbox"></mct-include>
</div>
<div class='right abs'>
<div class='right abs mobile-right'>
<div class='ui-symbol icon alert hidden' onclick="alert('Not yet functional. When this is visible, it means that this object needs to be updated. Clicking will allow that action via a dialog.');">!</div>
<div class='ui-symbol icon profile' title="Shared">P</div>
</div>
@@ -44,4 +44,7 @@
</div>
</div>
</div>
</div>
<div class="contents abs mobile-info desktop-hide">
<mct-representation class="contents abs btn s-very-subtle desktop-hide" key="'info-button'" mct-object="domainObject"></mct-representation>
</div>
</div>

View File

@@ -63,7 +63,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
@@ -126,6 +125,36 @@ 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 parent = navigationService.getNavigation().getCapability('context').getParent(),
grandparent;
if (parent.getId() !== ROOT_ID) {
grandparent = parent.getCapability('context').getParent().getId();
navigateTo(parent);
if (grandparent && grandparent !== ROOT_ID) {
$scope.atRoot = false;
} else {
$scope.atRoot = true;
}
} else {
$scope.atRoot = true;
}
}
function checkRoot() {
var parent = navigationService.getNavigation().getCapability('context').getParent();
if (parent.getId() !== ROOT_ID) {
$scope.atRoot = false;
} else {
$scope.atRoot = true;
}
}
// Load the root object, put it in the scope.
// Also, load its immediate children, and (possibly)
@@ -140,7 +169,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);
@@ -151,6 +186,10 @@ define(
$scope.$on("$destroy", function () {
navigationService.removeListener(setNavigation);
});
$scope.backArrow = navigateToParent;
$scope.checkRoot = checkRoot;
}

View File

@@ -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,6 +159,13 @@ 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 () {
mockScope.treeSlide();
});
it("releases its navigation listener when its scope is destroyed", function () {
expect(mockScope.$on).toHaveBeenCalledWith(
@@ -237,7 +258,104 @@ 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();
});
// 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();
});
});
}
);

View File

@@ -59,7 +59,7 @@
"glyph": "Z",
"name": "Remove",
"description": "Remove this object from its containing object.",
"depends": [ "$q" ]
"depends": [ "$q", "navigationService" ]
},
{
"key": "save",

View File

@@ -40,7 +40,7 @@ define(
* @constructor
* @memberof module:editor/actions/remove-action
*/
function RemoveAction($q, context) {
function RemoveAction($q, navigationService, context) {
var object = (context || {}).domainObject;
/**
@@ -69,14 +69,25 @@ define(
return persistence && persistence.persist();
}
// Checks current object with object being removed
function checkCurrentObjectNavigation(object, parent) {
var currentObj = navigationService.getNavigation();
if (currentObj.getId() === object.getId()) {
navigationService.setNavigation(parent);
}
}
/**
* Remove the object from its parent, as identified by its context
* capability.
* @param {ContextCapability} contextCapability the "context" capability
* of the domain object being removed.
* @param {object} domain object being removed contextCapability
gotten from the "context" capability of this object
*/
function removeFromContext(contextCapability) {
var parent = contextCapability.getParent();
function removeFromContext(object) {
var contextCapability = object.getCapability('context'),
parent = contextCapability.getParent();
// Navigates to parent if deleting current object
checkCurrentObjectNavigation(object, parent);
$q.when(
parent.useCapability('mutation', doMutate)
).then(function () {
@@ -91,7 +102,7 @@ define(
* fulfilled when the action has completed.
*/
perform: function () {
return $q.when(object.getCapability('context'))
return $q.when(object)
.then(removeFromContext);
}
};

View File

@@ -28,6 +28,7 @@ define(
describe("The Remove action", function () {
var mockQ,
mockNavigationService,
mockDomainObject,
mockParent,
mockContext,
@@ -64,19 +65,32 @@ define(
},
useCapability: function (k, v) {
return capabilities[k].invoke(v);
},
getId: function () {
return "test";
}
};
mockContext = jasmine.createSpyObj("context", [ "getParent" ]);
mockMutation = jasmine.createSpyObj("mutation", [ "invoke" ]);
mockPersistence = jasmine.createSpyObj("persistence", [ "persist" ]);
mockType = jasmine.createSpyObj("type", [ "hasFeature" ]);
mockNavigationService = jasmine.createSpyObj(
"navigationService",
[
"getNavigation",
"setNavigation",
"addListener",
"removeListener"
]
);
mockNavigationService.getNavigation.andReturn(mockDomainObject);
mockDomainObject.getId.andReturn("test");
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getParent.andReturn(mockParent);
mockType.hasFeature.andReturn(true);
capabilities = {
mutation: mockMutation,
persistence: mockPersistence,
@@ -88,7 +102,7 @@ define(
actionContext = { domainObject: mockDomainObject };
action = new RemoveAction(mockQ, actionContext);
action = new RemoveAction(mockQ, mockNavigationService, actionContext);
});
it("only applies to objects with parents", function () {

View File

@@ -8,6 +8,11 @@
"key": "urlService",
"implementation": "/services/UrlService.js",
"depends": [ "$location" ]
},
{
"key": "agentService",
"implementation": "/services/AgentService.js",
"depends": [ "$window" ]
}
],
"runs": [
@@ -60,7 +65,7 @@
{
"key": "TreeNodeController",
"implementation": "controllers/TreeNodeController.js",
"depends": [ "$scope", "$timeout" ]
"depends": [ "$scope", "$timeout", "agentService" ]
},
{
"key": "ActionGroupController",

View File

@@ -48,6 +48,33 @@
/************************** 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.
*****************************************************************************/
/************************** 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
@@ -120,6 +147,27 @@
* 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;
@@ -392,7 +440,7 @@ input[type="text"] {
margin: 0 0 2px 2px;
overflow: hidden;
position: relative; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../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%;
@@ -401,10 +449,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 166, ../sass/_mixins.scss */
.form-control.select:not(.disabled):hover.btn-menu .invoke-menu {
color: #878787; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.form-control.select.btn-menu .invoke-menu {
color: #757575; }
/* line 29, ../sass/forms/_selects.scss */

View File

@@ -48,6 +48,33 @@
/************************** 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.
*****************************************************************************/
/************************** 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
@@ -78,6 +105,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
@@ -136,7 +184,7 @@
margin-bottom: 3px;
margin-right: 3px;
position: relative; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../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%;
@@ -145,10 +193,10 @@
background-image: -webkit-linear-gradient(#707070, #636363);
background-image: linear-gradient(#707070, #636363);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.items-holder .item.grid-item:not(.disabled):hover.btn-menu .invoke-menu {
color: #949494; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.items-holder .item.grid-item.btn-menu .invoke-menu {
color: #828282; }
/* line 46, ../sass/items/_item.scss */
@@ -269,7 +317,7 @@
color: #999;
display: inline-block;
color: #80dfff; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../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%;
@@ -278,10 +326,10 @@
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
background-image: linear-gradient(#2ecbff, #14c4ff);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.items-holder .item.grid-item.selected:not(.disabled):hover.btn-menu .invoke-menu {
color: #75ddff; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.items-holder .item.grid-item.selected.btn-menu .invoke-menu {
color: #52d4ff; }
/* line 140, ../sass/items/_item.scss */
@@ -296,3 +344,105 @@
/* line 144, ../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 34, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-grid-nav {
top: 0px;
bottom: 0px;
right: 55px; }
/* line 39, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-info {
text-align: center;
width: 50px;
right: 0px;
left: auto;
font-size: 1.3em; }
/* line 47, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .bar.bottom-bar.abs {
top: 0px;
height: auto; }
/* line 54, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .item-main .item-type {
font-size: 30px;
top: 0px;
left: 0px;
text-align: left;
height: auto; }
/* line 61, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .item-main .item-open {
display: none; }
/* line 65, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .title, .items-holder .item.grid-item .details {
margin-left: 30px; } }
@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 {
width: 100%;
height: 50px; }
/* line 74, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-right {
top: 100%; }
/* line 77, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-info {
line-height: 25px; }
/* line 81, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .item-main .item-type {
line-height: 40px; }
/* line 85, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .title {
margin-right: 10px;
line-height: 25px; }
/* line 89, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .details {
margin-right: 10px;
line-height: 0px; } }
@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 {
width: 100%;
height: 66.66667px; }
/* line 99, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-right {
top: 100%; }
/* line 103, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .mobile-info {
line-height: 38px; }
/* line 107, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .item-main .item-type {
font-size: 30px;
line-height: 50px; }
/* line 112, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .title {
margin-right: 10px;
line-height: 38px; }
/* line 116, ../sass/mobile/_item.scss */
.items-holder .item.grid-item .details {
margin-right: 10px;
line-height: 0px; } }
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 29, ../sass/mobile/_item.scss */
.items-holder .item.grid-item {
width: 200px;
height: 200px; } }

View File

@@ -49,6 +49,33 @@
/************************** 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.
*****************************************************************************/
/************************** 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
@@ -92,7 +119,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* line 5, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 5, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
@@ -113,38 +140,38 @@ time, mark, audio, video {
font-size: 100%;
vertical-align: baseline; }
/* line 22, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 22, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html {
line-height: 1; }
/* line 24, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 24, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none; }
/* line 26, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 26, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0; }
/* line 28, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 28, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
/* line 30, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 30, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none; }
/* line 103, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 103, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none; }
/* line 32, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 32, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
a img {
border: none; }
/* line 116, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 116, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
display: block; }
@@ -178,6 +205,27 @@ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
}
}
*/
/*****************************************************************************
* 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
@@ -664,21 +712,251 @@ mct-container {
/* line 267, ../sass/user-environ/_layout.scss */
.split-layout.vertical > .pane {
margin-left: 5px; }
/* line 269, ../sass/user-environ/_layout.scss */
/* line 270, ../sass/user-environ/_layout.scss */
.split-layout.vertical > .pane > .holder {
left: 0;
right: 0; }
/* line 273, ../sass/user-environ/_layout.scss */
/* line 274, ../sass/user-environ/_layout.scss */
.split-layout.vertical > .pane:first-child {
margin-left: 0; }
/* line 275, ../sass/user-environ/_layout.scss */
/* line 276, ../sass/user-environ/_layout.scss */
.split-layout.vertical > .pane:first-child .holder {
right: 3px; }
/* line 284, ../sass/user-environ/_layout.scss */
/* line 285, ../sass/user-environ/_layout.scss */
.vscroll {
overflow-y: auto; }
/*****************************************************************************
* 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 26, ../sass/mobile/_layout.scss */
.browse-wrapper,
.mobile-pane {
position: absolute;
left: 0;
top: 0;
right: 0;
white-space: nowrap; } }
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 38, ../sass/mobile/_layout.scss */
.desktop-browse {
min-width: 150px;
max-width: 800px;
width: 25%; } }
@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 49, ../sass/mobile/_layout.scss */
.browse-hidetree {
-moz-user-select: -moz-none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none; } }
@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 60, ../sass/mobile/_layout.scss */
.browse-hidetree .mobile-pane.left-menu {
-moz-transition-property: opacity;
-o-transition-property: opacity;
-webkit-transition-property: opacity;
transition-property: opacity;
-moz-transition-duration: 0.4s;
-o-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
-moz-transition-timing-function: ease-in-out;
-o-transition-timing-function: ease-in-out;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
opacity: 0;
right: 100% !important;
width: auto !important;
overflow-y: hidden;
overflow-x: hidden; } }
@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 73, ../sass/mobile/_layout.scss */
.browse-hidetree .mobile-pane.right-repr {
-moz-transition-duration: 0.35s;
-o-transition-duration: 0.35s;
-webkit-transition-duration: 0.35s;
transition-duration: 0.35s;
transition-timing-function: ease;
backface-visibility: hidden;
left: auto !important;
width: 100% !important; } }
/* line 82, ../sass/mobile/_layout.scss */
.mobile-tree-holder {
top: 30px; }
@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 91, ../sass/mobile/_layout.scss */
.browse-showtree {
-moz-user-select: -moz-none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none; } }
@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 102, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.left-menu {
-moz-transition-property: opacity;
-o-transition-property: opacity;
-webkit-transition-property: opacity;
transition-property: opacity;
-moz-transition-duration: 0.4s;
-o-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
-moz-transition-timing-function: ease-in-out;
-o-transition-timing-function: ease-in-out;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
opacity: 1;
display: block !important;
width: auto !important; } }
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px) {
/* line 102, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.left-menu {
right: 19px !important; } }
@media 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 102, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.left-menu {
right: 66% !important; } }
@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) {
/* line 102, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.left-menu {
right: 500px !important; } }
@media 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 102, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.left-menu {
right: 78% !important; } }
@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 126, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.right-repr {
-moz-transition-duration: 0.35s;
-o-transition-duration: 0.35s;
-webkit-transition-duration: 0.35s;
transition-duration: 0.35s;
transition-timing-function: ease;
backface-visibility: hidden;
left: auto !important; } }
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px) {
/* line 126, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.right-repr {
width: 19px !important; } }
@media 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 126, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.right-repr {
width: 66% !important; } }
@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) {
/* line 126, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.right-repr {
width: 500px !important; } }
@media 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 126, ../sass/mobile/_layout.scss */
.browse-showtree .mobile-pane.right-repr {
width: 78% !important; } }
@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 149, ../sass/mobile/_layout.scss */
.button-pos {
position: absolute; } }
@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 158, ../sass/mobile/_layout.scss */
.object-header {
position: relative;
left: 44px; }
/* line 163, ../sass/mobile/_layout.scss */
.object-header .label .context-available {
opacity: 1 !important; } }
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 170, ../sass/mobile/_layout.scss */
.desktop-hide {
display: none; } }
@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 177, ../sass/mobile/_layout.scss */
.mobile-hide {
display: none; } }
@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 183, ../sass/mobile/_layout.scss */
.mobile-important-hide {
display: none !important; } }
/* line 189, ../sass/mobile/_layout.scss */
.mobile-back-hide {
pointer-events: none;
-moz-transition-property: opacity;
-o-transition-property: opacity;
-webkit-transition-property: opacity;
transition-property: opacity;
-moz-transition-duration: 0.4s;
-o-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
-moz-transition-timing-function: ease-in-out;
-o-transition-timing-function: ease-in-out;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
opacity: 0; }
/* line 196, ../sass/mobile/_layout.scss */
.mobile-back-unhide {
pointer-events: all;
-moz-transition-property: opacity;
-o-transition-property: opacity;
-webkit-transition-property: opacity;
transition-property: opacity;
-moz-transition-duration: 0.4s;
-o-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
-moz-transition-timing-function: ease-in-out;
-o-transition-timing-function: ease-in-out;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
opacity: 1; }
@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 203, ../sass/mobile/_layout.scss */
.phone-hide {
display: none; } }
@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 209, ../sass/mobile/_layout.scss */
.tree-holder {
overflow-x: hidden !important; } }
@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 214, ../sass/mobile/_layout.scss */
.mobile-disable-select {
-moz-user-select: -moz-none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none; } }
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
@@ -1452,7 +1730,7 @@ mct-container {
color: #999;
display: inline-block;
color: #ccf2ff; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn.major:not(.disabled):hover,
.s-btn.major:not(.disabled):hover,
.major.icon-btn:not(.disabled):hover,
@@ -1464,13 +1742,13 @@ mct-container {
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
background-image: linear-gradient(#2ecbff, #14c4ff);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn.major:not(.disabled):hover.btn-menu .invoke-menu,
.s-btn.major:not(.disabled):hover.btn-menu .invoke-menu,
.major.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
.major.s-icon-btn:not(.disabled):hover.btn-menu .invoke-menu {
color: #75ddff; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn.major.btn-menu .invoke-menu,
.s-btn.major.btn-menu .invoke-menu,
.major.btn-menu.icon-btn .invoke-menu,
@@ -1500,7 +1778,7 @@ mct-container {
border-top: 1px solid #2ecbff;
color: #ccf2ff;
display: inline-block; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn.major:hover:not(.disabled):hover,
.s-btn.major:hover:not(.disabled):hover,
.major.icon-btn:hover:not(.disabled):hover,
@@ -1512,13 +1790,13 @@ mct-container {
background-image: -webkit-linear-gradient(#47d1ff, #2ecbff);
background-image: linear-gradient(#47d1ff, #2ecbff);
color: white; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn.major:hover:not(.disabled):hover.btn-menu .invoke-menu,
.s-btn.major:hover:not(.disabled):hover.btn-menu .invoke-menu,
.major.icon-btn:hover:not(.disabled):hover.btn-menu .invoke-menu,
.major.s-icon-btn:hover:not(.disabled):hover.btn-menu .invoke-menu {
color: #8fe3ff; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn.major:hover.btn-menu .invoke-menu,
.s-btn.major:hover.btn-menu .invoke-menu,
.major.icon-btn:hover.btn-menu .invoke-menu,
@@ -1554,7 +1832,7 @@ mct-container {
border-top: 1px solid #8a8a8a;
color: #cccccc;
display: inline-block; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn.subtle:not(.disabled):hover,
.s-btn.subtle:not(.disabled):hover,
.subtle.icon-btn:not(.disabled):hover,
@@ -1566,13 +1844,13 @@ mct-container {
background-image: -webkit-linear-gradient(#969696, #8a8a8a);
background-image: linear-gradient(#969696, #8a8a8a);
color: #f0f0f0; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn.subtle:not(.disabled):hover.btn-menu .invoke-menu,
.s-btn.subtle:not(.disabled):hover.btn-menu .invoke-menu,
.subtle.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
.subtle.s-icon-btn:not(.disabled):hover.btn-menu .invoke-menu {
color: #bababa; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn.subtle.btn-menu .invoke-menu,
.s-btn.subtle.btn-menu .invoke-menu,
.subtle.btn-menu.icon-btn .invoke-menu,
@@ -1605,7 +1883,7 @@ mct-container {
border-top: 1px solid #575757;
color: #999;
display: inline-block; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn.very-subtle:not(.disabled):hover, .btn.s-very-subtle:not(.disabled):hover,
.s-btn.very-subtle:not(.disabled):hover,
.very-subtle.icon-btn:not(.disabled):hover,
@@ -1620,7 +1898,7 @@ mct-container {
background-image: -webkit-linear-gradient(#636363, #575757);
background-image: linear-gradient(#636363, #575757);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn.very-subtle:not(.disabled):hover.btn-menu .invoke-menu, .btn.s-very-subtle:not(.disabled):hover.btn-menu .invoke-menu,
.s-btn.very-subtle:not(.disabled):hover.btn-menu .invoke-menu,
.very-subtle.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
@@ -1629,7 +1907,7 @@ mct-container {
.s-very-subtle.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
.s-very-subtle.s-icon-btn:not(.disabled):hover.btn-menu .invoke-menu {
color: #878787; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn.very-subtle.btn-menu .invoke-menu, .btn.s-very-subtle.btn-menu .invoke-menu,
.s-btn.very-subtle.btn-menu .invoke-menu,
.very-subtle.btn-menu.icon-btn .invoke-menu,
@@ -1665,7 +1943,7 @@ mct-container {
border-top: 1px solid #fe9510;
color: #fff;
display: inline-block; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn.very-subtle.paused:not(.disabled):hover, .btn.s-very-subtle.paused:not(.disabled):hover,
.s-btn.very-subtle.paused:not(.disabled):hover,
.very-subtle.paused.icon-btn:not(.disabled):hover,
@@ -1680,7 +1958,7 @@ mct-container {
background-image: -webkit-linear-gradient(#fea029, #fe9510);
background-image: linear-gradient(#fea029, #fe9510);
color: white; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn.very-subtle.paused:not(.disabled):hover.btn-menu .invoke-menu, .btn.s-very-subtle.paused:not(.disabled):hover.btn-menu .invoke-menu,
.s-btn.very-subtle.paused:not(.disabled):hover.btn-menu .invoke-menu,
.very-subtle.paused.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
@@ -1689,7 +1967,7 @@ mct-container {
.s-very-subtle.paused.icon-btn:not(.disabled):hover.btn-menu .invoke-menu,
.s-very-subtle.paused.s-icon-btn:not(.disabled):hover.btn-menu .invoke-menu {
color: #fec070; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn.very-subtle.paused.btn-menu .invoke-menu, .btn.s-very-subtle.paused.btn-menu .invoke-menu,
.s-btn.very-subtle.paused.btn-menu .invoke-menu,
.very-subtle.paused.btn-menu.icon-btn .invoke-menu,
@@ -2141,7 +2419,7 @@ label.checkbox.custom {
color: lighten($c, 10%);
}
}*/ }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.btn-menu:not(.disabled):hover {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
@@ -2150,10 +2428,10 @@ label.checkbox.custom {
background-image: -webkit-linear-gradient(#636363, #575757);
background-image: linear-gradient(#636363, #575757);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.btn-menu:not(.disabled):hover.btn-menu .invoke-menu {
color: #878787; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.btn-menu.btn-menu .invoke-menu {
color: #757575; }
/* line 285, ../sass/controls/_controls.scss */
@@ -2299,7 +2577,7 @@ label.checkbox.custom {
auto: 0;
bottom: auto;
left: auto; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
@@ -2308,13 +2586,13 @@ label.checkbox.custom {
background-image: -webkit-linear-gradient(#636363, #575757);
background-image: linear-gradient(#636363, #575757);
color: #bdbdbd; }
/* line 165, ../sass/_mixins.scss */
/* line 166, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover.btn-menu .invoke-menu {
color: #878787; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.slider .knob.btn-menu .invoke-menu {
color: #757575; }
/* line 186, ../sass/_mixins.scss */
/* line 187, ../sass/_mixins.scss */
.slider .knob:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";
@@ -2338,7 +2616,7 @@ label.checkbox.custom {
left: 2px;
bottom: 5px;
top: 5px; }
/* line 208, ../sass/_mixins.scss */
/* line 209, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";
@@ -2510,14 +2788,14 @@ label.checkbox.custom {
padding: 3px 0;
position: absolute;
z-index: 10; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.menu-element .menu.btn-menu .invoke-menu {
color: #828282; }
/* line 37, ../sass/controls/_menus.scss */
.menu-element .menu ul {
margin: 0;
padding: 0; }
/* line 276, ../sass/_mixins.scss */
/* line 277, ../sass/_mixins.scss */
.menu-element .menu ul li {
list-style-type: none;
margin: 0;
@@ -2568,7 +2846,7 @@ label.checkbox.custom {
border-top: 1px solid #919191;
color: #999;
display: inline-block; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.menu-element .context-menu.btn-menu .invoke-menu,
.menu-element .super-menu.btn-menu .invoke-menu {
color: #b0b0b0; }
@@ -2686,6 +2964,40 @@ label.checkbox.custom {
right: 0;
width: auto; }
/*****************************************************************************
* 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 25, ../sass/mobile/controls/_menus.scss */
.mobile-menu-icon {
display: inline-block; }
@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 25, ../sass/mobile/controls/_menus.scss */
.mobile-menu-icon {
font-size: 21px;
padding-top: 1px; } }
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 25, ../sass/mobile/controls/_menus.scss */
.mobile-menu-icon {
display: none; } }
/* line 1, ../sass/controls/_time-controller.scss */
.l-time-controller {
position: relative;
@@ -3442,7 +3754,7 @@ input[type="text"] {
margin: 0 0 2px 2px;
overflow: hidden;
position: relative; }
/* line 162, ../sass/_mixins.scss */
/* line 163, ../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%;
@@ -3451,10 +3763,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 166, ../sass/_mixins.scss */
.form-control.select:not(.disabled):hover.btn-menu .invoke-menu {
color: #878787; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.form-control.select.btn-menu .invoke-menu {
color: #757575; }
/* line 29, ../sass/forms/_selects.scss */
@@ -4073,7 +4385,7 @@ input[type="text"] {
bottom: 15%;
left: 15%;
z-index: 101; }
/* line 170, ../sass/_mixins.scss */
/* line 171, ../sass/_mixins.scss */
.overlay > .holder.btn-menu .invoke-menu {
color: #757575; }
/* line 45, ../sass/overlay/_overlay.scss */
@@ -4118,6 +4430,17 @@ input[type="text"] {
left: 5px;
overflow: 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), 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 6, ../sass/mobile/overlay/_overlay.scss */
.overlay > .holder {
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
top: 0;
right: 0;
bottom: 0;
left: 0; } }
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
@@ -4443,33 +4766,40 @@ input[type="text"] {
margin-left: 20px; }
/* line 80, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-left .l-infobubble::before {
right: 100%;
width: 0;
height: 0;
border-top: 6.66667px solid transparent;
border-bottom: 6.66667px solid transparent;
border-right: 10px solid #ddd; }
/* line 86, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right {
margin-right: 20px; }
/* line 88, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right .l-infobubble::before {
left: 100%;
width: 0;
height: 0;
border-top: 6.66667px solid transparent;
border-bottom: 6.66667px solid transparent;
border-left: 10px solid #ddd; }
/* line 95, ../sass/helpers/_bubbles.scss */
right: 100%; }
@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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 80, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-left .l-infobubble::before {
width: 0;
height: 0;
border-top: 6.66667px solid transparent;
border-bottom: 6.66667px solid transparent;
border-right: 10px solid #ddd; } }
@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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 92, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right {
margin-right: 20px; } }
/* line 99, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right .l-infobubble::before {
left: 100%; }
@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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 99, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right .l-infobubble::before {
width: 0;
height: 0;
border-top: 6.66667px solid transparent;
border-bottom: 6.66667px solid transparent;
border-left: 10px solid #ddd; } }
/* line 112, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-top .l-infobubble::before {
top: 20px; }
/* line 101, ../sass/helpers/_bubbles.scss */
/* line 118, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-btm .l-infobubble::before {
bottom: 20px; }
/* line 106, ../sass/helpers/_bubbles.scss */
/* line 123, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-down {
margin-bottom: 10px; }
/* line 108, ../sass/helpers/_bubbles.scss */
/* line 125, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-down .l-infobubble::before {
left: 50%;
top: 100%;
@@ -4477,21 +4807,21 @@ input[type="text"] {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 7.5px solid #ddd; }
/* line 117, ../sass/helpers/_bubbles.scss */
/* line 134, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .arw {
z-index: 2; }
/* line 120, ../sass/helpers/_bubbles.scss */
/* line 137, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-up .arw.arw-down, .l-infobubble-wrapper.arw-down .arw.arw-up {
display: none; }
/* line 127, ../sass/helpers/_bubbles.scss */
/* line 144, ../sass/helpers/_bubbles.scss */
.l-thumbsbubble-wrapper .arw-up {
width: 0;
height: 0;
border-left: 6.66667px solid transparent;
border-right: 6.66667px solid transparent;
border-bottom: 10px solid #4d4d4d; }
/* line 130, ../sass/helpers/_bubbles.scss */
/* line 147, ../sass/helpers/_bubbles.scss */
.l-thumbsbubble-wrapper .arw-down {
width: 0;
height: 0;
@@ -4499,7 +4829,7 @@ input[type="text"] {
border-right: 6.66667px solid transparent;
border-top: 10px solid #4d4d4d; }
/* line 134, ../sass/helpers/_bubbles.scss */
/* line 151, ../sass/helpers/_bubbles.scss */
.s-infobubble {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -4510,22 +4840,22 @@ input[type="text"] {
background: #ddd;
color: #666;
font-size: 0.8rem; }
/* line 141, ../sass/helpers/_bubbles.scss */
/* line 158, ../sass/helpers/_bubbles.scss */
.s-infobubble .title {
color: #333333;
font-weight: bold; }
/* line 146, ../sass/helpers/_bubbles.scss */
/* line 163, ../sass/helpers/_bubbles.scss */
.s-infobubble tr td {
border-top: 1px solid #c4c4c4;
font-size: 0.9em; }
/* line 150, ../sass/helpers/_bubbles.scss */
/* line 167, ../sass/helpers/_bubbles.scss */
.s-infobubble tr:first-child td {
border-top: none; }
/* line 154, ../sass/helpers/_bubbles.scss */
/* line 171, ../sass/helpers/_bubbles.scss */
.s-infobubble .value {
color: #333333; }
/* line 159, ../sass/helpers/_bubbles.scss */
/* line 176, ../sass/helpers/_bubbles.scss */
.s-thumbsbubble {
background: #4d4d4d;
color: #b3b3b3; }
@@ -4580,7 +4910,7 @@ input[type="text"] {
right: 0;
width: auto;
height: 5px; }
/* line 186, ../sass/_mixins.scss */
/* line 187, ../sass/_mixins.scss */
.split-layout.horizontal > .splitter:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";
@@ -4604,7 +4934,7 @@ input[type="text"] {
top: 2px;
left: 5px;
right: 5px; }
/* line 208, ../sass/_mixins.scss */
/* line 209, ../sass/_mixins.scss */
.split-layout.horizontal > .splitter:not(.disabled):hover:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";
@@ -4634,7 +4964,7 @@ input[type="text"] {
bottom: 0;
cursor: col-resize;
width: 5px; }
/* line 186, ../sass/_mixins.scss */
/* line 187, ../sass/_mixins.scss */
.split-layout.vertical > .splitter:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";
@@ -4658,7 +4988,7 @@ input[type="text"] {
left: 2px;
bottom: 5px;
top: 5px; }
/* line 208, ../sass/_mixins.scss */
/* line 209, ../sass/_mixins.scss */
.split-layout.vertical > .splitter:not(.disabled):hover:before {
-moz-transition-property: "border-color";
-o-transition-property: "border-color";

View File

@@ -48,6 +48,33 @@
/************************** 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.
*****************************************************************************/
/************************** 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
@@ -78,6 +105,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
@@ -103,7 +151,7 @@
ul.tree {
margin: 0;
padding: 0; }
/* line 276, ../sass/_mixins.scss */
/* line 277, ../sass/_mixins.scss */
ul.tree li {
list-style-type: none;
margin: 0;
@@ -133,10 +181,11 @@ ul.tree {
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 */
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 47, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .view-control:hover {
color: #ffc700; } }
/* line 53, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label {
display: block;
overflow: hidden;
@@ -148,7 +197,7 @@ ul.tree {
width: auto;
height: auto;
left: 15px; }
/* line 57, ../sass/tree/_tree.scss */
/* line 60, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .type-icon {
overflow: false;
position: absolute;
@@ -163,12 +212,12 @@ ul.tree {
left: 5px;
right: auto;
width: 1em; }
/* line 65, ../sass/tree/_tree.scss */
/* line 68, ../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 */
/* line 74, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .type-icon .icon.l-icon-alert {
color: #ff3c00;
font-size: 8px;
@@ -177,7 +226,7 @@ ul.tree {
width: 8px;
top: 1px;
right: -2px; }
/* line 77, ../sass/tree/_tree.scss */
/* line 80, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .type-icon .icon.l-icon-link {
color: #49dedb;
font-size: 8px;
@@ -186,7 +235,7 @@ ul.tree {
width: 8px;
left: -3px;
bottom: 5px; }
/* line 86, ../sass/tree/_tree.scss */
/* line 89, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .label .title-label {
overflow: hidden;
position: absolute;
@@ -201,51 +250,110 @@ ul.tree {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }
/* line 97, ../sass/tree/_tree.scss */
/* line 100, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading {
pointer-events: none; }
/* line 99, ../sass/tree/_tree.scss */
/* line 102, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .label {
opacity: 0.5; }
/* line 101, ../sass/tree/_tree.scss */
/* line 104, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .label .title-label {
font-style: italic; }
/* line 105, ../sass/tree/_tree.scss */
/* line 108, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.loading .wait-spinner {
margin-left: 14px; }
/* line 110, ../sass/tree/_tree.scss */
/* line 113, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.selected {
background: #005177;
color: #fff; }
/* line 114, ../sass/tree/_tree.scss */
/* line 117, ../sass/tree/_tree.scss */
ul.tree li span.tree-item.selected .view-control {
color: #0099cc; }
/* line 117, ../sass/tree/_tree.scss */
/* line 120, ../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 */
@media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
/* line 128, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover {
background: #404040;
color: #cccccc; }
/* line 131, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover .context-trigger {
display: block; }
/* line 134, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.selected):hover .icon {
color: #33ccff; } }
/* line 141, ../sass/tree/_tree.scss */
ul.tree li span.tree-item:not(.loading) {
cursor: pointer; }
/* line 139, ../sass/tree/_tree.scss */
/* line 145, ../sass/tree/_tree.scss */
ul.tree li span.tree-item .context-trigger {
top: -1px;
position: absolute;
right: 3px; }
/* line 145, ../sass/tree/_tree.scss */
/* line 151, ../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 160, ../sass/tree/_tree.scss */
ul.tree ul.tree {
margin-left: 15px; }
/*****************************************************************************
* 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 24, ../sass/mobile/_tree.scss */
ul.tree {
margin: 0;
padding: 0; }
/* line 277, ../sass/_mixins.scss */
ul.tree li {
list-style-type: none;
margin: 0;
padding: 0; }
/* line 29, ../sass/mobile/_tree.scss */
ul.tree li span.tree-item {
height: 38px;
line-height: 38px;
padding-top: 3px;
padding-bottom: 3px;
margin-bottom: 0px; }
/* line 36, ../sass/mobile/_tree.scss */
ul.tree li span.tree-item .view-control {
position: absolute;
right: 13px;
font-size: 1.8em;
right: 0px;
width: 35px;
text-align: center; }
/* line 45, ../sass/mobile/_tree.scss */
ul.tree li span.tree-item .label {
left: 3px;
right: 45px;
font-size: 1.2em; }
/* line 54, ../sass/mobile/_tree.scss */
ul.tree li span.tree-item .label .title-label {
right: 16.9px; }
/* line 63, ../sass/mobile/_tree.scss */
ul.tree ul.tree {
margin-left: 7px; } }

View File

@@ -27,10 +27,14 @@
@import "compass/utilities";
@import "mixins";
@import "mobile/mixins";
@import "effects";
@import "global";
@import "fonts";
@import "user-environ/layout";
@import "mobile/layout";
@import "fixed-position";
@import "about";
@import "text";
@@ -45,6 +49,7 @@
@import "controls/controls";
@import "controls/lists";
@import "controls/menus";
@import "mobile/controls/menus";
@import "controls/time-controller";
@import "edit/editor";
@import "features/imagery";
@@ -59,6 +64,7 @@
@import "forms/filter";
@import "plots/plots-main";
@import "overlay/overlay";
@import "mobile/overlay/overlay";
@import "user-environ/frame";
@import "user-environ/top-bar";
@import "user-environ/bottom-bar";

View File

@@ -19,6 +19,7 @@
* 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;

View File

@@ -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";

View File

@@ -79,15 +79,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);
}
}
}
@@ -124,12 +141,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 {
$emFg: darken($colorInfoBubbleFg, 20%);

View File

@@ -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";

View File

@@ -0,0 +1,87 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
$mobile-listIcon: 30px;
$mobile-listRight: 10px;
$phone-itemHeight: $ueBrowseGridItemLg/4;
$tablet-itemHeight: $ueBrowseGridItemLg/3;
/************************** MOBILE TREE MENU DIMENSIONS */
$mobile-treeHeight: 38px;
$mobile-startingTreeLeft: 3px;
$mobile-runningTreeLeft: 7px;
$mobile-treeRight: 13px;
/************************** 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 */
$phoneRepSizePortrait: 19px;
$phoneRepSizeLandscape: 66%;
$tabletRepSizePortrait: 500px;
$tabletRepSizeLandscape: 78%;
$desktopMenuSize: 25%;

View File

@@ -0,0 +1,130 @@
/*****************************************************************************
* 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 {
$dWid: $ueBrowseGridItemLg;
$dHei: $ueBrowseGridItemLg;
@include phoneandtablet {
$dWid: 100%;
.mobile-grid-nav {
top: 0px;
bottom: 0px;
right: 55px;
}
.mobile-info {
text-align: center;
width: 50px;
right: 0px;
left: auto;
font-size: 1.3em;
}
.bar {
&.bottom-bar.abs {
top: 0px;
height: auto;
}
}
.item-main {
.item-type {
font-size: $mobile-listIcon;
top: 0px;
left: 0px;
text-align: left;
height: auto
}
.item-open {
display: none;
}
}
.title, .details {
margin-left: $mobile-listIcon;
}
}
@include phone {
$dHei: $phone-itemHeight;
width: $dWid;
height: $dHei;
.mobile-right {
top: 100%;
}
.mobile-info {
line-height: $phone-itemHeight * .5;
}
.item-main {
.item-type {
line-height: $phone-itemHeight * .8;
}
}
.title {
margin-right: $mobile-listRight;
line-height: $phone-itemHeight * .5;
}
.details {
margin-right: $mobile-listRight;
line-height: 0px;
}
}
@include tablet {
$dHei: $tablet-itemHeight;
width: $dWid;
height: $dHei;
.mobile-right {
top: 100%;
}
.mobile-info {
line-height: $tablet-itemHeight * .57;
}
.item-main {
.item-type {
font-size: $mobile-listIcon;
line-height: $tablet-itemHeight * .75;
}
}
.title {
margin-right: $mobile-listRight;
line-height: $tablet-itemHeight * .57;
}
.details {
margin-right: $mobile-listRight;
line-height: 0px;
}
}
@include desktop {
$dWid: $ueBrowseGridItemLg;
$dHei: $ueBrowseGridItemLg;
width: $dWid;
height: $dHei;
}
}
}
}

View File

@@ -0,0 +1,218 @@
/*****************************************************************************
* 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.
*****************************************************************************/
// Wrapper of the entire 2 panes, only enacted on
// phone and tablet. Also for the panes
.browse-wrapper,
.mobile-pane {
@include phoneandtablet {
position: absolute;
left: 0; top: 0;
right: 0;
white-space: nowrap;
}
}
// Default views of the panels
// if in desktop browser
.desktop-browse {
@include desktop {
min-width: 150px;
max-width: 800px;
width: $desktopMenuSize;
}
}
// When the tree is hidden, these are the
// classes used for the left menu and the
// right representation.
.browse-hidetree {
// 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 phoneandtablet {
@include user-select(none);
}
// Sets the left tree menu when the tree
// is hidden.
.mobile-pane.left-menu {
@include phoneandtablet {
@include trans-prop-nice(opacity, .4s);
opacity: 0;
right: 100% !important;
width: auto !important;
overflow-y: hidden;
overflow-x: hidden;
}
}
// Sets the right represenation when
// the tree is hidden.
.mobile-pane.right-repr {
@include phoneandtablet {
@include slMenuTransitions;
left: auto !important;
width: 100% !important;
}
}
}
.mobile-tree-holder {
top: 30px;
}
// When the tree is shown, these are
// the classes used for the left menu
// and the right menu (for each device &
// orientation combination, separate
// parameters are used)
.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 phoneandtablet {
@include user-select(none);
}
// Sets the left tree menu when the tree
// is shown.
.mobile-pane.left-menu {
@include phoneandtablet {
@include trans-prop-nice(opacity, .4s);
opacity: 1;
display: block !important;
width: auto !important;
}
// On both phones and tablets, the amount of
// space allowed for the right pane is specified
@include phonePortrait {
right: $phoneRepSizePortrait !important;
}
@include phoneLandscape {
right: $phoneRepSizeLandscape !important;
}
@include tabletPortrait {
right: $tabletRepSizePortrait !important;
}
@include tabletLandscape {
right: $tabletRepSizeLandscape !important;
}
}
// Sets the right represenation when
// the tree is shown.
.mobile-pane.right-repr {
@include phoneandtablet {
@include slMenuTransitions;
left: auto !important;
}
// On both phones and tablets, the width of
// the right pane is specified
@include phonePortrait {
width: $phoneRepSizePortrait !important;
}
@include phoneLandscape {
width: $phoneRepSizeLandscape !important;
}
@include tabletPortrait {
width: $tabletRepSizePortrait !important;
}
@include tabletLandscape {
width: $tabletRepSizeLandscape !important;
}
}
}
// Button position is set as absolute with transitions
.button-pos {
@include phoneandtablet {
position: absolute;
}
}
// Object header must be moved
// over to make space for the
// hamburger icon
.object-header {
@include phoneandtablet {
position: relative;
left: 44px;
.label {
.context-available {
opacity: 1 !important;
}
}
}
}
.desktop-hide {
@include desktop {
display: none;
}
}
// Hides objects on phone and tablet
.mobile-hide {
@include phoneandtablet {
display: none;
}
}
.mobile-important-hide {
@include phoneandtablet {
display: none !important;
}
}
.mobile-back-hide {
pointer-events: none;
@include trans-prop-nice(opacity, .4s);
opacity: 0;
}
// Hides objects on phone and tablet
.mobile-back-unhide {
pointer-events: all;
@include trans-prop-nice(opacity, .4s);
opacity: 1;
}
// Hides objects only on the phone
.phone-hide {
@include phone {
display: none;
}
}
.tree-holder {
@include phoneandtablet {
overflow-x: hidden !important;
}
}
.mobile-disable-select {
@include phoneandtablet {
@include user-select(none);
}
}

View 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;
}

View File

@@ -0,0 +1,67 @@
/*****************************************************************************
* 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.
*****************************************************************************/
ul.tree {
// Only applies to phones and tablets
@include phoneandtablet {
@include menuUlReset();
li {
span.tree-item {
// Adds some space to the top of each tree item
height: $mobile-treeHeight;
line-height: $mobile-treeHeight;
padding-top: $interiorMarginSm;
padding-bottom: $interiorMarginSm;
margin-bottom: 0px;
.view-control {
position: absolute;
right: $mobile-treeRight;
font-size: 1.8em;
right: 0px;
width: 35px;
text-align: center;
}
.label {
// Designates the starting left margin
// (indentation) of 'My Items'
// Also adds right space for selection button
left: $mobile-startingTreeLeft;
right: 45px;
font-size: 1.2em;
// Allows tree item name to stop prior
// to the arrow
.title-label {
right: $mobile-treeRight * 1.3;
}
}
}
}
// Sets the margin on the left, which causes the
// running indentation after each folder is made
ul.tree {
margin-left: $mobile-runningTreeLeft;
}
}
}

View File

@@ -0,0 +1,34 @@
/*****************************************************************************
* 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.
*****************************************************************************/
// Mobile hamburger icon is
// sized according to the device
.mobile-menu-icon {
display: inline-block;
@include phoneandtablet {
font-size: 21px;
padding-top: $imageThumbPad;
}
@include desktop {
display: none;
}
}

View File

@@ -0,0 +1,11 @@
.overlay {
@include phoneandtablet {
$m: 0;
// Removes curved edges on the dialog box
// and makes it take up fullscreen
>.holder {
@include border-radius($m);
top: $m; right: $m; bottom: $m; left: $m;
}
}
}

View File

@@ -20,5 +20,6 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
@import "constants";
@import "mobile/constants";
@import "themes/theme-espresso";
@import "main";

View File

@@ -26,5 +26,8 @@
@import "compass/utilities";
@import "constants";
@import "mobile/constants";
@import "mixins";
@import "tree/tree";
@import "mobile/mixins";
@import "tree/tree";
@import "mobile/tree";

View File

@@ -42,9 +42,12 @@ ul.tree {
font-size: 0.75em;
width: $treeVCW;
$runningItemW: $interiorMargin + $treeVCW;
&:hover {
color: $colorItemTreeVCHover;
}
// NOTE: [Mobile] Removed Hover on Mobile
@include desktop {
&:hover {
color: $colorItemTreeVCHover;
}
}
}
.label {
@@ -120,16 +123,19 @@ ul.tree {
}
&:not(.selected) {
&:hover {
background: lighten($colorBodyBg, 5%);
color: lighten($colorBodyFg, 20%);
.context-trigger {
display: block;
}
.icon {
color: $colorItemTreeIconHover;
}
}
// NOTE: [Mobile] Removed Hover on Mobile
@include desktop {
&:hover {
background: lighten($colorBodyBg, 5%);
color: lighten($colorBodyFg, 20%);
.context-trigger {
display: block;
}
.icon {
color: $colorItemTreeIconHover;
}
}
}
}
&:not(.loading) {

View File

@@ -265,6 +265,7 @@
&.vertical {
// Slides left and right
>.pane {
// @include test();
margin-left: $interiorMargin;
>.holder {
left: 0;

View File

@@ -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"

View File

@@ -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>

View File

@@ -25,20 +25,24 @@
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>
<mct-representation
key="'label'"
<mct-representation
key="'label'"
mct-object="domainObject"
ng-model="ngModel"
ng-click="ngModel.selectedObject = domainObject"
ng-click="!treeNode.checkMobile() ? ngModel.selectedObject = domainObject :
toggle.toggle(); treeNode.trackExpansion()"
>
</mct-representation>
<span
class='ui-symbol view-control'
mct-object="domainObject"
ng-model="ngModel"
ng-click="treeNode.checkMobile() ? ngModel.selectedObject = domainObject :
toggle.toggle(); treeNode.trackExpansion()"
ng-if="model.composition !== undefined || treeNode.checkMobile()"
>
{{treeNode.checkMobile() ? "}" : toggle.isActive() ? "v" : ">"}}
</span>
</span>
<span
class="tree-item-subtree"

View File

@@ -50,7 +50,7 @@ define(
* expand-to-show-navigated-object behavior.)
* @constructor
*/
function TreeNodeController($scope, $timeout, $rootScope) {
function TreeNodeController($scope, $timeout, agentService) {
var selectedObject = ($scope.ngModel || {}).selectedObject,
isSelected = false,
hasBeenExpanded = false;
@@ -86,7 +86,11 @@ define(
$timeout(function () { hasBeenExpanded = true; }, 0);
}
}
function checkMobile() {
return agentService.isMobile(navigator.userAgent);
}
// Consider the currently-navigated object and update
// parameters which support display.
function checkSelection() {
@@ -150,6 +154,9 @@ define(
* lazy loading of the node's subtree.
*/
trackExpansion: trackExpansion,
checkMobile: checkMobile,
/**
* Check if this not has ever been expanded.
* @returns true if it has been expanded

View File

@@ -0,0 +1,102 @@
/*****************************************************************************
* 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($window) {
// 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
function getOrientation() {
if ($window.outerWidth > $window.outerHeight) {
return "landscape";
} else if ($window.outerWidth < $window.outerHeight) {
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;
}
);

View File

@@ -64,7 +64,7 @@ define(
"index.html#" + urlForLocation(mode, domainObject) + viewPath;
return newTabPath;
}
return {
/**
* Returns the Url path for a specific domain object

View File

@@ -29,6 +29,7 @@ define(
describe("The tree node controller", function () {
var mockScope,
mockTimeout,
mockAgentService,
controller;
function TestObject(id, context) {
@@ -43,7 +44,8 @@ define(
beforeEach(function () {
mockScope = jasmine.createSpyObj("$scope", ["$watch", "$on"]);
mockTimeout = jasmine.createSpy("$timeout");
controller = new TreeNodeController(mockScope, mockTimeout);
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
controller = new TreeNodeController(mockScope, mockTimeout, mockAgentService);
});
it("allows tracking of expansion state", function () {
@@ -183,6 +185,12 @@ define(
expect(controller.isSelected()).toBeFalsy();
});
it("check if tree node is in a mobile device", function () {
if (controller) {
controller.checkMobile();
}
});
});
}
);

View File

@@ -0,0 +1,74 @@
/*****************************************************************************
* 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",
[ "outerWidth", "outerHeight" ]
);
mockNavigator = jasmine.createSpyObj(
"navigator",
[ "userAgent" ]
);
agentService = new AgentService(mockWindow);
});
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 () {
mockWindow.outerWidth = 768;
mockWindow.outerHeight = 1024;
agentService.getOrientation();
mockWindow.outerWidth = 1024;
mockWindow.outerHeight = 768;
agentService.getOrientation();
});
});
}
);

View File

@@ -91,7 +91,7 @@ define(
it("get url for a new tab using domainObject and mode", function () {
urlService.urlForNewTab(mockMode, mockDomainObject);
});
});
});
}
);

View File

@@ -13,6 +13,7 @@
"directives/MCTDrag",
"directives/MCTResize",
"directives/MCTScroll",
"services/AgentService",
"services/UrlService",
"StyleSheetLoader"
]

View File

@@ -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" ]
}
]
}
}

View File

@@ -0,0 +1,26 @@
<!--
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)-->
<div>
<a class='ui-symbol icon mobile-info'>i</a>
</div>

View 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);
// 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;
}
);

View File

@@ -38,7 +38,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 dismissBubble,
pendingBubble,
mousePosition,
@@ -71,7 +71,7 @@ define(
function showBubble(event) {
trackPosition(event);
// Also need to track position during hover
element.on('mousemove', trackPosition);
@@ -85,14 +85,20 @@ define(
mousePosition
);
element.off('mousemove', trackPosition);
pendingBubble = undefined;
}, DELAY);
element.on('mouseleave', hideBubble);
}
// Show bubble (on a timeout) on mouse over
element.on('mouseenter', showBubble);
// 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', showBubble);
}
// Also make sure we dismiss bubble if representation is destroyed
// before the mouse actually leaves it

View File

@@ -33,7 +33,7 @@ define(
* Displays informative content ("info bubbles") for the user.
* @constructor
*/
function InfoService($compile, $document, $window, $rootScope) {
function InfoService($compile, $document, $window, $rootScope, agentService) {
function display(templateKey, title, content, position) {
var body = $document.find('body'),
@@ -54,22 +54,33 @@ define(
// Create the context menu
bubble = $compile(BUBBLE_TEMPLATE)(scope);
// Position the bubble
// Position the bubble:
// Phone: On a phone the bubble is specifically positioned
// so that it takes up the width of the screen.
// Tablet/Desktop: On other devices with larger screens, the
// info bubble positioned as normal (with triangle pointing
// to where clicked or pressed)
bubble.css('position', 'absolute');
if (goLeft) {
bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
if (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 (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');
}
}
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
body.append(bubble);
// Return a function to dismiss the bubble
return function () { bubble.remove(); };
}

View 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)
);
});
});
}
);

View File

@@ -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,

View File

@@ -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]);
});
});
});

View File

@@ -1,4 +1,5 @@
[
"gestures/InfoGesture",
"gestures/InfoButtonGesture",
"services/InfoService"
]

View 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.

View 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", "$log", "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."
}
]
}
}

View 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>

View 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>

View File

@@ -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>

View 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;
}
);

View File

@@ -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;
}
);

View 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, $log, 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;
}
);

View File

@@ -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: "="
}
};
};
}
);

View 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;
}
);

View 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;
}
);

View 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;
}
);

View 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;
}
};
}
);

View 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;
}
);

View 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;
});

View 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;
}
);

View File

@@ -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>

View File

@@ -177,7 +177,7 @@ define(
// Unsubscribe when the plot is destroyed
$scope.$on("$destroy", releaseSubscription);
// Create a throttled update function
scheduleUpdate = throttle(function () {
modeOptions.getModeHandler().getSubPlots()

View File

@@ -17,7 +17,7 @@
},
{
"key": "ELASTIC_ROOT",
"value": "http://localhost:9200",
"value": "/elastic",
"priority": "fallback"
},
{

View File

@@ -26,7 +26,7 @@
{
"key": "menu",
"implementation": "gestures/ContextMenuGesture.js",
"depends": []
"depends": ["$timeout", "agentService"]
}
],
"components": [
@@ -54,7 +54,7 @@
{
"key": "menu",
"implementation": "actions/ContextMenuAction.js",
"depends": [ "$compile", "$document", "$window", "$rootScope" ]
"depends": [ "$compile", "$document", "$window", "$rootScope", "agentService" ]
}
]
}

View File

@@ -47,7 +47,7 @@ define(
* @param actionContexr the context in which the action
* should be performed
*/
function ContextMenuAction($compile, $document, $window, $rootScope, actionContext) {
function ContextMenuAction($compile, $document, $window, $rootScope, agentService, actionContext) {
function perform() {
var winDim = [$window.innerWidth, $window.innerHeight],
@@ -94,13 +94,26 @@ define(
body.append(menu);
// Stop propagation so that clicks on the menu do not close the menu
menu.on('mousedown', function (event) {
event.stopPropagation();
});
// Stop propagation so that touches on the menu do not close the menu
if (!agentService.isMobile(navigator.userAgent)) {
menu.on('mousedown', function (event) {
event.stopPropagation();
});
} else if (agentService.isMobile(navigator.userAgent)) {
menu.on('touchstart', function (event) {
event.stopPropagation();
});
}
// Dismiss the menu when body is clicked elsewhere
// Dismiss the menu when body is clicked/touched elsewhere
// ('mousedown' because 'click' breaks left-click context menus)
body.on('mousedown', dismiss);
// ('touchstart' because 'touch' breaks context menus up)
if (!agentService.isMobile(navigator.userAgent)) {
body.on('mousedown', dismiss);
} else if (agentService.isMobile(navigator.userAgent)) {
body.on('touchstart', dismiss);
}
// Don't launch browser's context menu
actionContext.event.preventDefault();

View File

@@ -39,16 +39,40 @@ define(
* @param {DomainObject} domainObject the object on which actions
* in the context menu will be performed
*/
function ContextMenuGesture(element, domainObject) {
function ContextMenuGesture($timeout, agentService, element, domainObject) {
var actionContext,
stop;
stop,
isPressing,
longTouchTime = 500;
// When context menu event occurs, show object actions instead
element.on('contextmenu', function (event) {
actionContext = {key: 'menu', domainObject: domainObject, event: event};
stop = domainObject.getCapability('action').perform(actionContext);
});
if (!agentService.isMobile(navigator.userAgent)) {
element.on('contextmenu', function (event) {
actionContext = {key: 'menu', domainObject: domainObject, event: event};
stop = domainObject.getCapability('action').perform(actionContext);
});
} else if (agentService.isMobile(navigator.userAgent)) {
// If on mobile device, then start timeout for the single touch event
// during the timeout 'isPressing' is true.
element.on('touchstart', function (event) {
if (event.touches.length < 2) {
isPressing = true;
// After the timeout, if 'isPressing' is
// true, display context menu for object
$timeout(function () {
if (isPressing) {
actionContext = {key: 'menu', domainObject: domainObject, event: event};
stop = domainObject.getCapability('action').perform(actionContext);
}
}, longTouchTime);
}
});
// Whenever the touch event ends, 'isPressing' is false.
element.on('touchend', function (event) {
isPressing = false;
});
}
return {
/**
* Detach any event handlers associated with this gesture.

View File

@@ -43,13 +43,24 @@ define(
mockBody,
mockWindow,
mockRootScope,
mockAgentService,
mockScope,
mockElement,
mockDomainObject,
mockEvent,
mockActionContext,
mockNavigator,
mockStopPropagation,
action;
function fireEvent(evt, value) {
mockElement.on.calls.forEach(function (call) {
if (call.args[0] === evt) {
call.args[1](value);
}
});
}
beforeEach(function () {
mockCompile = jasmine.createSpy("$compile");
mockCompiledTemplate = jasmine.createSpy("template");
@@ -58,10 +69,11 @@ define(
mockBody = jasmine.createSpyObj("body", JQLITE_FUNCTIONS);
mockWindow = { innerWidth: MENU_DIMENSIONS[0] * 4, innerHeight: MENU_DIMENSIONS[1] * 4 };
mockRootScope = jasmine.createSpyObj("$rootScope", ["$new"]);
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
mockScope = {};
mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS);
mockDomainObject = jasmine.createSpyObj("domainObject", DOMAIN_OBJECT_METHODS);
mockEvent = jasmine.createSpyObj("event", ["preventDefault"]);
mockEvent = jasmine.createSpyObj("event", ["preventDefault", "stopPropagation"]);
mockEvent.pageX = 0;
mockEvent.pageY = 0;
@@ -71,12 +83,13 @@ define(
mockRootScope.$new.andReturn(mockScope);
mockActionContext = {key: 'menu', domainObject: mockDomainObject, event: mockEvent};
action = new ContextMenuAction(
mockCompile,
mockDocument,
mockWindow,
mockRootScope,
mockAgentService,
mockActionContext
);
});
@@ -135,6 +148,42 @@ define(
// Listener should have been detached from body
expect(mockBody.off).toHaveBeenCalled();
});
it("keeps a menu when menu is clicked", function () {
// Show the menu
action.perform();
// Find and fire body's mousedown listener
mockMenu.on.calls.forEach(function (call) {
if (call.args[0] === 'mousedown') {
call.args[1](mockEvent);
}
});
// Menu should have been removed
expect(mockMenu.remove).not.toHaveBeenCalled();
// Listener should have been detached from body
expect(mockBody.off).not.toHaveBeenCalled();
});
it("keeps a menu when menu is clicked on mobile", function () {
mockAgentService.isMobile.andReturn(true);
action = new ContextMenuAction(
mockCompile,
mockDocument,
mockWindow,
mockRootScope,
mockAgentService,
mockActionContext
);
action.perform();
mockMenu.on.calls.forEach(function (call) {
if (call.args[0] === 'touchstart') {
call.args[1](mockEvent);
}
});
});
});
}
);

View File

@@ -31,28 +31,54 @@ define(
"use strict";
var JQLITE_FUNCTIONS = [ "on", "off", "find", "append", "remove" ],
DOMAIN_OBJECT_METHODS = [ "getId", "getModel", "getCapability", "hasCapability", "useCapability" ];
DOMAIN_OBJECT_METHODS = [ "getId", "getModel", "getCapability", "hasCapability", "useCapability"];
describe("The 'context menu' gesture", function () {
var mockElement,
var mockTimeout,
mockElement,
mockAgentService,
mockDomainObject,
mockEvent,
mockTouchEvent,
mockContextMenuAction,
mockActionContext,
mockTouch,
gesture,
fireGesture;
fireGesture,
fireTouchStartGesture,
fireTouchEndGesture;
beforeEach(function () {
mockTimeout = jasmine.createSpy("$timeout");
mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS);
mockAgentService = jasmine.createSpyObj("agentService", ["isMobile"]);
mockDomainObject = jasmine.createSpyObj("domainObject", DOMAIN_OBJECT_METHODS);
mockEvent = jasmine.createSpyObj("event", ["preventDefault"]);
gesture = new ContextMenuGesture(mockElement, mockDomainObject);
mockContextMenuAction = jasmine.createSpyObj(
"action",
[ "perform", "getActions" ]
);
mockActionContext = jasmine.createSpyObj(
"actionContext",
[ "" ]
);
mockActionContext = {domainObject: mockDomainObject, event: mockEvent};
mockDomainObject.getCapability.andReturn(mockContextMenuAction);
mockContextMenuAction.perform.andReturn(jasmine.any(Function));
mockAgentService.isMobile.andReturn(false);
gesture = new ContextMenuGesture(mockTimeout, mockAgentService, mockElement, mockDomainObject);
// Capture the contextmenu callback
fireGesture = mockElement.on.mostRecentCall.args[1];
});
it("attaches a callback for context menu events", function () {
// Fire a click and expect it to happen
fireGesture();
expect(mockElement.on).toHaveBeenCalledWith(
"contextmenu",
jasmine.any(Function)
@@ -70,6 +96,34 @@ define(
mockDomainObject.calls
);
});
it("attaches a callback for context menu events on mobile", function () {
// Mock touch event and set to mobile device
mockTouchEvent = jasmine.createSpyObj("event", ["preventDefault", "touches"]);
mockTouch = jasmine.createSpyObj("touch", ["length"]);
mockTouch.length = 1;
mockTouchEvent.touches.andReturn(mockTouch);
mockAgentService.isMobile.andReturn(true);
// Then create new (mobile) gesture
gesture = new ContextMenuGesture(mockTimeout, mockAgentService, mockElement, mockDomainObject);
// Set calls for the touchstart and touchend gestures
fireTouchStartGesture = mockElement.on.calls[1].args[1];
fireTouchEndGesture = mockElement.on.mostRecentCall.args[1];
// Fire touchstart and expect touch start to begin
fireTouchStartGesture(mockTouchEvent);
expect(mockElement.on).toHaveBeenCalledWith(
"touchstart",
jasmine.any(Function)
);
// Expect timeout to begin and then fireTouchEnd
expect(mockTimeout).toHaveBeenCalled();
mockTimeout.mostRecentCall.args[0]();
fireTouchEndGesture(mockTouchEvent);
});
});
}
);