mirror of
https://github.com/nasa/openmct.git
synced 2025-05-29 13:44:21 +00:00
[Style] JSLint Compliance
This commit is contained in:
parent
a0dc3da8fb
commit
056b3f61ce
@ -7,15 +7,17 @@ define(
|
|||||||
|
|
||||||
// TODO: Store this in more accessible locations / retrieve from
|
// TODO: Store this in more accessible locations / retrieve from
|
||||||
// domainObject metadata.
|
// domainObject metadata.
|
||||||
var DOMAIN_INTERVAL = 1 * 60 * 1000; // One minute.
|
var DOMAIN_INTERVAL = 2 * 60 * 1000; // Two minutes.
|
||||||
|
|
||||||
function PlotController($scope, colorService) {
|
function PlotController($scope, colorService) {
|
||||||
var plotHistory = [];
|
var plotHistory = [],
|
||||||
var isLive = true;
|
isLive = true,
|
||||||
var maxDomain = +new Date();
|
maxDomain = +new Date(),
|
||||||
var subscriptions = [];
|
subscriptions = [],
|
||||||
var palette = new colorService.ColorPalette();
|
palette = new colorService.ColorPalette();
|
||||||
var setToDefaultViewport = function() {
|
|
||||||
|
|
||||||
|
function setToDefaultViewport() {
|
||||||
// TODO: We shouldn't set the viewport until we have received data or something has given us a reasonable viewport.
|
// TODO: We shouldn't set the viewport until we have received data or something has given us a reasonable viewport.
|
||||||
$scope.viewport = {
|
$scope.viewport = {
|
||||||
topLeft: {
|
topLeft: {
|
||||||
@ -27,15 +29,15 @@ define(
|
|||||||
range: -1
|
range: -1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
setToDefaultViewport();
|
setToDefaultViewport();
|
||||||
|
|
||||||
$scope.displayableRange = function(rangeValue) {
|
$scope.displayableRange = function (rangeValue) {
|
||||||
// TODO: Call format function provided by domain object.
|
// TODO: Call format function provided by domain object.
|
||||||
return rangeValue;
|
return rangeValue;
|
||||||
};
|
};
|
||||||
$scope.displayableDomain = function(domainValue) {
|
$scope.displayableDomain = function (domainValue) {
|
||||||
// TODO: Call format function provided by domain object.
|
// TODO: Call format function provided by domain object.
|
||||||
return new Date(domainValue).toUTCString();
|
return new Date(domainValue).toUTCString();
|
||||||
};
|
};
|
||||||
@ -44,25 +46,33 @@ define(
|
|||||||
|
|
||||||
$scope.rectangles = [];
|
$scope.rectangles = [];
|
||||||
|
|
||||||
var updateSeriesFromTelemetry = function(series, seriesIndex, telemetry) {
|
function updateSeriesFromTelemetry(series, seriesIndex, telemetry) {
|
||||||
var domainValue = telemetry.getDomainValue(telemetry.getPointCount() - 1);
|
var domainValue = telemetry.getDomainValue(
|
||||||
var rangeValue = telemetry.getRangeValue(telemetry.getPointCount() - 1);
|
telemetry.getPointCount() - 1
|
||||||
|
),
|
||||||
|
rangeValue = telemetry.getRangeValue(
|
||||||
|
telemetry.getPointCount() - 1
|
||||||
|
),
|
||||||
|
newTelemetry;
|
||||||
// Track the biggest domain we've seen for sticky-ness.
|
// Track the biggest domain we've seen for sticky-ness.
|
||||||
maxDomain = Math.max(maxDomain, domainValue);
|
maxDomain = Math.max(maxDomain, domainValue);
|
||||||
|
|
||||||
var newTelemetry = {
|
newTelemetry = {
|
||||||
domain: domainValue,
|
domain: domainValue,
|
||||||
range: rangeValue
|
range: rangeValue
|
||||||
};
|
};
|
||||||
series.data.push(newTelemetry);
|
series.data.push(newTelemetry);
|
||||||
$scope.$broadcast('series:data:add', seriesIndex, [newTelemetry]);
|
$scope.$broadcast('series:data:add', seriesIndex, [newTelemetry]);
|
||||||
};
|
}
|
||||||
|
|
||||||
var subscribeToDomainObject = function(domainObject) {
|
function subscribeToDomainObject(domainObject) {
|
||||||
var telemetryCapability = domainObject.getCapability('telemetry');
|
var telemetryCapability = domainObject.getCapability('telemetry'),
|
||||||
var model = domainObject.getModel();
|
model = domainObject.getModel(),
|
||||||
|
series,
|
||||||
|
seriesIndex,
|
||||||
|
updater;
|
||||||
|
|
||||||
var series = {
|
series = {
|
||||||
name: model.name,
|
name: model.name,
|
||||||
// TODO: Bring back PlotPalette.
|
// TODO: Bring back PlotPalette.
|
||||||
color: palette.getColor($scope.series.length),
|
color: palette.getColor($scope.series.length),
|
||||||
@ -70,17 +80,25 @@ define(
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.series.push(series);
|
$scope.series.push(series);
|
||||||
var seriesIndex = $scope.series.indexOf(series);
|
seriesIndex = $scope.series.indexOf(series);
|
||||||
|
|
||||||
var updater = updateSeriesFromTelemetry.bind(
|
updater = updateSeriesFromTelemetry.bind(
|
||||||
null,
|
null,
|
||||||
series,
|
series,
|
||||||
seriesIndex
|
seriesIndex
|
||||||
);
|
);
|
||||||
subscriptions.push(telemetryCapability.subscribe(updater));
|
subscriptions.push(telemetryCapability.subscribe(updater));
|
||||||
};
|
}
|
||||||
|
|
||||||
var linkDomainObject = function(domainObject) {
|
function unlinkDomainObject() {
|
||||||
|
subscriptions.forEach(function(subscription) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
});
|
||||||
|
subscriptions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function linkDomainObject(domainObject) {
|
||||||
unlinkDomainObject();
|
unlinkDomainObject();
|
||||||
if (domainObject.hasCapability('telemetry')) {
|
if (domainObject.hasCapability('telemetry')) {
|
||||||
subscribeToDomainObject(domainObject);
|
subscribeToDomainObject(domainObject);
|
||||||
@ -98,23 +116,17 @@ define(
|
|||||||
} else {
|
} else {
|
||||||
throw new Error('Domain object type not supported.');
|
throw new Error('Domain object type not supported.');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var unlinkDomainObject = function() {
|
|
||||||
subscriptions.forEach(function(subscription) {
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
subscriptions = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
var onUserViewportChangeStart = function() {
|
function onUserViewportChangeStart() {
|
||||||
// TODO: this is a great time to track a history entry.
|
// TODO: this is a great time to track a history entry.
|
||||||
// Disable live mode so they have full control of viewport.
|
// Disable live mode so they have full control of viewport.
|
||||||
plotHistory.push($scope.viewport);
|
plotHistory.push($scope.viewport);
|
||||||
isLive = false;
|
isLive = false;
|
||||||
};
|
}
|
||||||
|
|
||||||
var onUserViewportChangeEnd = function(event, viewport) {
|
function onUserViewportChangeEnd(event, viewport) {
|
||||||
// If the new viewport is "close enough" to the maxDomain then
|
// If the new viewport is "close enough" to the maxDomain then
|
||||||
// enable live mode. Set empirically to 10% of the domain
|
// enable live mode. Set empirically to 10% of the domain
|
||||||
// interval.
|
// interval.
|
||||||
@ -127,10 +139,10 @@ define(
|
|||||||
isLive = false;
|
isLive = false;
|
||||||
}
|
}
|
||||||
plotHistory.push(viewport);
|
plotHistory.push(viewport);
|
||||||
};
|
}
|
||||||
|
|
||||||
var viewportForMaxDomain = function() {
|
function viewportForMaxDomain() {
|
||||||
var viewport = {
|
return {
|
||||||
topLeft: {
|
topLeft: {
|
||||||
range: $scope.viewport.topLeft.range,
|
range: $scope.viewport.topLeft.range,
|
||||||
domain: maxDomain - DOMAIN_INTERVAL
|
domain: maxDomain - DOMAIN_INTERVAL
|
||||||
@ -140,14 +152,13 @@ define(
|
|||||||
domain: maxDomain
|
domain: maxDomain
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return viewport;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
var followDataIfLive = function() {
|
function followDataIfLive() {
|
||||||
if (isLive) {
|
if (isLive) {
|
||||||
$scope.viewport = viewportForMaxDomain();
|
$scope.viewport = viewportForMaxDomain();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
$scope.$on('series:data:add', followDataIfLive);
|
$scope.$on('series:data:add', followDataIfLive);
|
||||||
$scope.$on('user:viewport:change:end', onUserViewportChangeEnd);
|
$scope.$on('user:viewport:change:end', onUserViewportChangeEnd);
|
||||||
@ -155,7 +166,7 @@ define(
|
|||||||
|
|
||||||
$scope.$watch('domainObject', linkDomainObject);
|
$scope.$watch('domainObject', linkDomainObject);
|
||||||
|
|
||||||
var controller = {
|
return {
|
||||||
historyBack: function() {
|
historyBack: function() {
|
||||||
// TODO: Step History Back.
|
// TODO: Step History Back.
|
||||||
},
|
},
|
||||||
@ -166,8 +177,6 @@ define(
|
|||||||
// TODO: Reset view to defaults. Keep history stack alive?
|
// TODO: Reset view to defaults. Keep history stack alive?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return controller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PlotController;
|
return PlotController;
|
||||||
|
@ -51,24 +51,6 @@ define(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 createOffset() {
|
function createOffset() {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
return;
|
return;
|
||||||
@ -84,18 +66,30 @@ define(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawIfResized() {
|
function lineFromSeries(series) {
|
||||||
if (canvas.width !== canvas.offsetWidth ||
|
// TODO: handle when lines get longer than 10,000 points.
|
||||||
canvas.height !== canvas.offsetHeight) {
|
// Each line allocates 10,000 points. This should be more
|
||||||
redraw();
|
// 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.
|
||||||
function destroyChart() {
|
//
|
||||||
isDestroyed = true;
|
// As long as the controller replaces $scope.series with a
|
||||||
if (activeInterval) {
|
// new series object, then this directive will
|
||||||
$interval.cancel(activeInterval);
|
// 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() {
|
function drawSeries() {
|
||||||
@ -132,7 +126,10 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateViewport() {
|
function updateViewport() {
|
||||||
var dimensions = [
|
var dimensions,
|
||||||
|
origin;
|
||||||
|
|
||||||
|
dimensions = [
|
||||||
Math.abs(
|
Math.abs(
|
||||||
offset.domain($scope.viewport.topLeft.domain) -
|
offset.domain($scope.viewport.topLeft.domain) -
|
||||||
offset.domain($scope.viewport.bottomRight.domain)
|
offset.domain($scope.viewport.bottomRight.domain)
|
||||||
@ -143,7 +140,7 @@ define(
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
var origin = [
|
origin = [
|
||||||
offset.domain(
|
offset.domain(
|
||||||
$scope.viewport.topLeft.domain
|
$scope.viewport.topLeft.domain
|
||||||
),
|
),
|
||||||
@ -158,31 +155,6 @@ define(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
for (var 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 onSeriesDataAdd(event, seriesIndex, points) {
|
function onSeriesDataAdd(event, seriesIndex, points) {
|
||||||
var line = lines[seriesIndex];
|
var line = lines[seriesIndex];
|
||||||
points.forEach(function (point) {
|
points.forEach(function (point) {
|
||||||
@ -192,6 +164,41 @@ define(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
// Check for resize, on a timer
|
||||||
activeInterval = $interval(drawIfResized, 1000);
|
activeInterval = $interval(drawIfResized, 1000);
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ define(
|
|||||||
function (utils) {
|
function (utils) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var RANGE_TICK_COUNT = 7;
|
var RANGE_TICK_COUNT = 7,
|
||||||
var DOMAIN_TICK_COUNT = 5;
|
DOMAIN_TICK_COUNT = 5;
|
||||||
|
|
||||||
function MCTPlot() {
|
function MCTPlot() {
|
||||||
|
|
||||||
@ -40,34 +40,37 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var dragStart;
|
var dragStart,
|
||||||
var marqueeBox = {};
|
marqueeBox = {},
|
||||||
var marqueeRect; // Set when exists.
|
marqueeRect, // Set when exists.
|
||||||
var chartElementBounds;
|
chartElementBounds,
|
||||||
var $canvas = $element.find('canvas');
|
$canvas = $element.find('canvas');
|
||||||
|
|
||||||
var updateAxesForCurrentViewport = function() {
|
function updateAxesForCurrentViewport() {
|
||||||
// Update axes definitions for current viewport.
|
// Update axes definitions for current viewport.
|
||||||
['domain', 'range'].forEach(function(axisName) {
|
['domain', 'range'].forEach(function(axisName) {
|
||||||
var axis = $scope.axes[axisName];
|
var axis = $scope.axes[axisName],
|
||||||
var firstTick = $scope.viewport.topLeft[axisName];
|
firstTick = $scope.viewport.topLeft[axisName],
|
||||||
var lastTick = $scope.viewport.bottomRight[axisName];
|
lastTick = $scope.viewport.bottomRight[axisName],
|
||||||
var axisSize = firstTick - lastTick;
|
axisSize = firstTick - lastTick,
|
||||||
var denominator = axis.tickCount - 1;
|
denominator = axis.tickCount - 1,
|
||||||
|
tickNumber,
|
||||||
|
tickIncrement,
|
||||||
|
tickValue;
|
||||||
// Yes, ticksize is negative for domain and positive for range.
|
// Yes, ticksize is negative for domain and positive for range.
|
||||||
// It's because ticks are generated/displayed top to bottom and left to right.
|
// It's because ticks are generated/displayed top to bottom and left to right.
|
||||||
axis.ticks = [];
|
axis.ticks = [];
|
||||||
for (var tickNumber = 0; tickNumber < axis.tickCount; tickNumber++) {
|
for (tickNumber = 0; tickNumber < axis.tickCount; tickNumber++) {
|
||||||
var tickIncrement = (axisSize * (tickNumber / denominator));
|
tickIncrement = (axisSize * (tickNumber / denominator));
|
||||||
var tickValue = firstTick - tickIncrement;
|
tickValue = firstTick - tickIncrement;
|
||||||
axis.ticks.push(
|
axis.ticks.push(
|
||||||
tickValue
|
tickValue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
var drawMarquee = function() {
|
function drawMarquee() {
|
||||||
// Create rectangle for Marquee if it should be set.
|
// Create rectangle for Marquee if it should be set.
|
||||||
if (marqueeBox && marqueeBox.start && marqueeBox.end) {
|
if (marqueeBox && marqueeBox.start && marqueeBox.end) {
|
||||||
if (!marqueeRect) {
|
if (!marqueeRect) {
|
||||||
@ -79,30 +82,88 @@ define(
|
|||||||
marqueeRect.color = [1, 1, 1, 0.5];
|
marqueeRect.color = [1, 1, 1, 0.5];
|
||||||
marqueeRect.layer = 'top'; // TODO: implement this.
|
marqueeRect.layer = 'top'; // TODO: implement this.
|
||||||
$scope.$broadcast('rectangle-change');
|
$scope.$broadcast('rectangle-change');
|
||||||
} else if (marqueeRect && $scope.rectangles.indexOf(marqueeRect) != -1) {
|
} else if (marqueeRect && $scope.rectangles.indexOf(marqueeRect) !== -1) {
|
||||||
$scope.rectangles.splice($scope.rectangles.indexOf(marqueeRect));
|
$scope.rectangles.splice($scope.rectangles.indexOf(marqueeRect));
|
||||||
marqueeRect = undefined;
|
marqueeRect = undefined;
|
||||||
$scope.$broadcast('rectangle-change');
|
$scope.$broadcast('rectangle-change');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var untrackMousePosition = function() {
|
function untrackMousePosition() {
|
||||||
$scope.mouseCoordinates = undefined;
|
$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);
|
||||||
|
|
||||||
var trackMousePosition = function($event) {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackMousePosition($event) {
|
||||||
// Calculate coordinates of mouse related to canvas and as
|
// Calculate coordinates of mouse related to canvas and as
|
||||||
// domain, range value and make available in scope for display.
|
// domain, range value and make available in scope for display.
|
||||||
|
|
||||||
var bounds = $event.target.getBoundingClientRect();
|
var bounds = $event.target.getBoundingClientRect(),
|
||||||
|
positionOverElement,
|
||||||
|
positionAsPlotPoint;
|
||||||
|
|
||||||
chartElementBounds = bounds;
|
chartElementBounds = bounds;
|
||||||
|
|
||||||
var positionOverElement = {
|
positionOverElement = {
|
||||||
x: $event.clientX - bounds.left,
|
x: $event.clientX - bounds.left,
|
||||||
y: $event.clientY - bounds.top
|
y: $event.clientY - bounds.top
|
||||||
};
|
};
|
||||||
|
|
||||||
var positionAsPlotPoint = utils.elementPositionAsPlotPosition(
|
positionAsPlotPoint = utils.elementPositionAsPlotPosition(
|
||||||
positionOverElement,
|
positionOverElement,
|
||||||
bounds,
|
bounds,
|
||||||
$scope.viewport
|
$scope.viewport
|
||||||
@ -120,104 +181,46 @@ define(
|
|||||||
if (dragStart) {
|
if (dragStart) {
|
||||||
updateDrag();
|
updateDrag();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var startMarquee = function() {
|
function watchForMarquee() {
|
||||||
marqueeBox.start = $scope.mouseCoordinates.positionAsPlotPoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateMarquee = function() {
|
|
||||||
// Update the marquee box in progress.
|
|
||||||
marqueeBox.end = $scope.mouseCoordinates.positionAsPlotPoint;
|
|
||||||
drawMarquee();
|
|
||||||
};
|
|
||||||
|
|
||||||
var endMarquee = function() {
|
|
||||||
// marqueeBox start/end are opposite corners but we need
|
|
||||||
// topLeft and bottomRight.
|
|
||||||
var boxPoints = utils.boxPointsFromOppositeCorners(marqueeBox.start, marqueeBox.end);
|
|
||||||
var newViewport = utils.oppositeCornersFromBoxPoints(boxPoints);
|
|
||||||
|
|
||||||
marqueeBox = {};
|
|
||||||
drawMarquee();
|
|
||||||
$scope.$emit('user:viewport:change:end', newViewport);
|
|
||||||
$scope.viewport = newViewport;
|
|
||||||
};
|
|
||||||
|
|
||||||
var startDrag = function($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;
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateDrag = function() {
|
|
||||||
// calculate offset between points. Apply that offset to viewport.
|
|
||||||
var newPosition = $scope.mouseCoordinates.positionAsPlotPoint;
|
|
||||||
var dDomain = dragStart.domain - newPosition.domain;
|
|
||||||
var 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
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var endDrag = function() {
|
|
||||||
dragStart = undefined;
|
|
||||||
$scope.$emit('user:viewport:change:end', $scope.viewport);
|
|
||||||
};
|
|
||||||
|
|
||||||
var watchForMarquee = function() {
|
|
||||||
$canvas.removeClass('plot-drag');
|
$canvas.removeClass('plot-drag');
|
||||||
$canvas.addClass('plot-marquee');
|
$canvas.addClass('plot-marquee');
|
||||||
$canvas.on('mousedown', startMarquee);
|
$canvas.on('mousedown', startMarquee);
|
||||||
$canvas.on('mouseup', endMarquee);
|
$canvas.on('mouseup', endMarquee);
|
||||||
$canvas.off('mousedown', startDrag);
|
$canvas.off('mousedown', startDrag);
|
||||||
$canvas.off('mouseup', endDrag);
|
$canvas.off('mouseup', endDrag);
|
||||||
};
|
}
|
||||||
|
|
||||||
var watchForDrag = function() {
|
function watchForDrag() {
|
||||||
$canvas.addClass('plot-drag');
|
$canvas.addClass('plot-drag');
|
||||||
$canvas.removeClass('plot-marquee');
|
$canvas.removeClass('plot-marquee');
|
||||||
$canvas.on('mousedown', startDrag);
|
$canvas.on('mousedown', startDrag);
|
||||||
$canvas.on('mouseup', endDrag);
|
$canvas.on('mouseup', endDrag);
|
||||||
$canvas.off('mousedown', startMarquee);
|
$canvas.off('mousedown', startMarquee);
|
||||||
$canvas.off('mouseup', endMarquee);
|
$canvas.off('mouseup', endMarquee);
|
||||||
};
|
}
|
||||||
|
|
||||||
var stopWatching = function() {
|
function toggleInteractionMode(event) {
|
||||||
|
if (event.keyCode === '18') { // control key.
|
||||||
|
watchForDrag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetInteractionMode(event) {
|
||||||
|
if (event.keyCode === '18') {
|
||||||
|
watchForMarquee();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopWatching() {
|
||||||
$canvas.off('mousedown', startDrag);
|
$canvas.off('mousedown', startDrag);
|
||||||
$canvas.off('mouseup', endDrag);
|
$canvas.off('mouseup', endDrag);
|
||||||
$canvas.off('mousedown', startMarquee);
|
$canvas.off('mousedown', startMarquee);
|
||||||
$canvas.off('mouseup', endMarquee);
|
$canvas.off('mouseup', endMarquee);
|
||||||
window.removeEventListener('keydown', toggleInteractionMode);
|
window.removeEventListener('keydown', toggleInteractionMode);
|
||||||
window.removeEventListener('keyup', resetInteractionMode);
|
window.removeEventListener('keyup', resetInteractionMode);
|
||||||
};
|
}
|
||||||
|
|
||||||
var toggleInteractionMode = function(event) {
|
|
||||||
if (event.keyCode == '18') { // control key.
|
|
||||||
watchForDrag();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var resetInteractionMode = function(event) {
|
|
||||||
if (event.keyCode == '18') {
|
|
||||||
watchForMarquee();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$canvas.on('mousemove', trackMousePosition);
|
$canvas.on('mousemove', trackMousePosition);
|
||||||
$canvas.on('mouseleave', untrackMousePosition);
|
$canvas.on('mouseleave', untrackMousePosition);
|
||||||
@ -226,7 +229,7 @@ define(
|
|||||||
window.addEventListener('keydown', toggleInteractionMode);
|
window.addEventListener('keydown', toggleInteractionMode);
|
||||||
window.addEventListener('keyup', resetInteractionMode);
|
window.addEventListener('keyup', resetInteractionMode);
|
||||||
|
|
||||||
var onViewportChange = function() {
|
function onViewportChange() {
|
||||||
if ($scope.mouseCoordinates && chartElementBounds) {
|
if ($scope.mouseCoordinates && chartElementBounds) {
|
||||||
$scope.mouseCoordinates.positionAsPlotPoint =
|
$scope.mouseCoordinates.positionAsPlotPoint =
|
||||||
utils.elementPositionAsPlotPosition(
|
utils.elementPositionAsPlotPosition(
|
||||||
@ -235,11 +238,9 @@ define(
|
|||||||
$scope.viewport
|
$scope.viewport
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (marqueeBox && marqueeBox.start) {
|
// TODO: Discuss whether marqueeBox start should be fixed to data or fixed to canvas element, especially when "isLive is true".
|
||||||
// TODO: Discuss whether marqueeBox start should be fixed to data or fixed to canvas element, especially when "isLive is true".
|
|
||||||
}
|
|
||||||
updateAxesForCurrentViewport();
|
updateAxesForCurrentViewport();
|
||||||
};
|
}
|
||||||
|
|
||||||
$scope.$watchCollection('viewport', onViewportChange);
|
$scope.$watchCollection('viewport', onViewportChange);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*global define */
|
/*global define,$log */
|
||||||
|
|
||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
@ -25,7 +25,8 @@ define(
|
|||||||
the draw API to.
|
the draw API to.
|
||||||
*/
|
*/
|
||||||
getDrawAPI: function (canvas) {
|
getDrawAPI: function (canvas) {
|
||||||
for (var i = 0; i < CHARTS.length; i++) {
|
var i;
|
||||||
|
for (i = 0; i < CHARTS.length; i++) {
|
||||||
try {
|
try {
|
||||||
return new CHARTS[i](canvas);
|
return new CHARTS[i](canvas);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -42,4 +43,4 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user