+ mct-drag-down="trCtrl.startMiddleDrag()"
+ mct-drag="trCtrl.middleDrag(delta[0])"
+ ng-style="{
+ left: startInnerPct,
+ right: endInnerPct
+ }">
diff --git a/platform/commonUI/general/src/controllers/TimeRangeController.js b/platform/commonUI/general/src/controllers/TimeRangeController.js
index f0e3da46d9..3ee05e1faf 100644
--- a/platform/commonUI/general/src/controllers/TimeRangeController.js
+++ b/platform/commonUI/general/src/controllers/TimeRangeController.js
@@ -19,247 +19,259 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
-/*global define,Promise*/
+/*global define*/
-define(
- ['moment'],
- function (moment) {
- "use strict";
+define([
- var TICK_SPACING_PX = 150;
+], function () {
+ "use strict";
+ var TICK_SPACING_PX = 150;
- /**
- * Controller used by the `time-controller` template.
- * @memberof platform/commonUI/general
- * @constructor
- * @param $scope the Angular scope for this controller
- * @param {FormatService} formatService the service to user to format
- * domain values
- * @param {string} defaultFormat the format to request when no
- * format has been otherwise specified
- * @param {Function} now a function to return current system time
- */
- function TimeRangeController($scope, formatService, defaultFormat, now) {
- var tickCount = 2,
- innerMinimumSpan = 1000, // 1 second
- outerMinimumSpan = 1000, // 1 second
- initialDragValue,
- formatter = formatService.getFormat(defaultFormat);
-
- function formatTimestamp(ts) {
- return formatter.format(ts);
- }
-
- // From 0.0-1.0 to "0%"-"100%"
- function toPercent(p) {
- return (100 * p) + "%";
- }
-
- function updateTicks() {
- var i, p, ts, start, end, span;
- end = $scope.ngModel.outer.end;
- start = $scope.ngModel.outer.start;
- span = end - start;
- $scope.ticks = [];
- for (i = 0; i < tickCount; i += 1) {
- p = i / (tickCount - 1);
- ts = p * span + start;
- $scope.ticks.push(formatTimestamp(ts));
- }
- }
-
- function updateSpanWidth(w) {
- tickCount = Math.max(Math.floor(w / TICK_SPACING_PX), 2);
- updateTicks();
- }
-
- function updateViewForInnerSpanFromModel(ngModel) {
- var span = ngModel.outer.end - ngModel.outer.start;
-
- // Expose readable dates for the knobs
- $scope.startInnerText = formatTimestamp(ngModel.inner.start);
- $scope.endInnerText = formatTimestamp(ngModel.inner.end);
-
- // And positions for the knobs
- $scope.startInnerPct =
- toPercent((ngModel.inner.start - ngModel.outer.start) / span);
- $scope.endInnerPct =
- toPercent((ngModel.outer.end - ngModel.inner.end) / span);
- }
-
- function defaultBounds() {
- var t = now();
- return {
- start: t - 24 * 3600 * 1000, // One day
- end: t
- };
- }
-
- function copyBounds(bounds) {
- return { start: bounds.start, end: bounds.end };
- }
-
- function updateViewFromModel(ngModel) {
- ngModel = ngModel || {};
- ngModel.outer = ngModel.outer || defaultBounds();
- ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
-
- // Stick it back is scope (in case we just set defaults)
- $scope.ngModel = ngModel;
-
- updateViewForInnerSpanFromModel(ngModel);
- updateTicks();
- }
-
- function startLeftDrag() {
- initialDragValue = $scope.ngModel.inner.start;
- }
-
- function startRightDrag() {
- initialDragValue = $scope.ngModel.inner.end;
- }
-
- function startMiddleDrag() {
- initialDragValue = {
- start: $scope.ngModel.inner.start,
- end: $scope.ngModel.inner.end
- };
- }
-
- function toMillis(pixels) {
- var span =
- $scope.ngModel.outer.end - $scope.ngModel.outer.start;
- return (pixels / $scope.spanWidth) * span;
- }
-
- function clamp(value, low, high) {
- return Math.max(low, Math.min(high, value));
- }
-
- function leftDrag(pixels) {
- var delta = toMillis(pixels);
- $scope.ngModel.inner.start = clamp(
- initialDragValue + delta,
- $scope.ngModel.outer.start,
- $scope.ngModel.inner.end - innerMinimumSpan
- );
- updateViewFromModel($scope.ngModel);
- }
-
- function rightDrag(pixels) {
- var delta = toMillis(pixels);
- $scope.ngModel.inner.end = clamp(
- initialDragValue + delta,
- $scope.ngModel.inner.start + innerMinimumSpan,
- $scope.ngModel.outer.end
- );
- updateViewFromModel($scope.ngModel);
- }
-
- function middleDrag(pixels) {
- var delta = toMillis(pixels),
- edge = delta < 0 ? 'start' : 'end',
- opposite = delta < 0 ? 'end' : 'start';
-
- // Adjust the position of the edge in the direction of drag
- $scope.ngModel.inner[edge] = clamp(
- initialDragValue[edge] + delta,
- $scope.ngModel.outer.start,
- $scope.ngModel.outer.end
- );
- // Adjust opposite knob to maintain span
- $scope.ngModel.inner[opposite] = $scope.ngModel.inner[edge] +
- initialDragValue[opposite] - initialDragValue[edge];
-
- updateViewFromModel($scope.ngModel);
- }
-
- function updateFormModel() {
- $scope.formModel = {
- start: (($scope.ngModel || {}).outer || {}).start,
- end: (($scope.ngModel || {}).outer || {}).end
- };
- }
-
- function updateOuterStart(t) {
- var ngModel = $scope.ngModel;
-
- ngModel.inner.start =
- Math.max(ngModel.outer.start, ngModel.inner.start);
- ngModel.inner.end = Math.max(
- ngModel.inner.start + innerMinimumSpan,
- ngModel.inner.end
- );
-
- updateFormModel();
- updateViewForInnerSpanFromModel(ngModel);
- updateTicks();
- }
-
- function updateOuterEnd(t) {
- var ngModel = $scope.ngModel;
-
- ngModel.inner.end =
- Math.min(ngModel.outer.end, ngModel.inner.end);
- ngModel.inner.start = Math.min(
- ngModel.inner.end - innerMinimumSpan,
- ngModel.inner.start
- );
-
- updateFormModel();
- updateViewForInnerSpanFromModel(ngModel);
- updateTicks();
- }
-
- function updateFormat(key) {
- formatter = formatService.getFormat(key || defaultFormat);
- updateViewForInnerSpanFromModel($scope.ngModel);
- updateTicks();
- }
-
- function updateBoundsFromForm() {
- var start = $scope.formModel.start,
- end = $scope.formModel.end;
- if (end >= start + outerMinimumSpan) {
- $scope.ngModel = $scope.ngModel || {};
- $scope.ngModel.outer = { start: start, end: end };
- }
- }
-
- function validateStart(startValue) {
- return startValue <= $scope.formModel.end - outerMinimumSpan;
- }
-
- function validateEnd(endValue) {
- return endValue >= $scope.formModel.start + outerMinimumSpan;
- }
-
- $scope.startLeftDrag = startLeftDrag;
- $scope.startRightDrag = startRightDrag;
- $scope.startMiddleDrag = startMiddleDrag;
- $scope.leftDrag = leftDrag;
- $scope.rightDrag = rightDrag;
- $scope.middleDrag = middleDrag;
-
- $scope.updateBoundsFromForm = updateBoundsFromForm;
-
- $scope.validateStart = validateStart;
- $scope.validateEnd = validateEnd;
-
- $scope.ticks = [];
-
- // Initialize scope to defaults
- updateViewFromModel($scope.ngModel);
- updateFormModel();
-
- $scope.$watchCollection("ngModel", updateViewFromModel);
- $scope.$watch("spanWidth", updateSpanWidth);
- $scope.$watch("ngModel.outer.start", updateOuterStart);
- $scope.$watch("ngModel.outer.end", updateOuterEnd);
- $scope.$watch("parameters.format", updateFormat);
- }
-
- return TimeRangeController;
+ /* format number as percent; 0.0-1.0 to "0%"-"100%" */
+ function toPercent(p) {
+ return (100 * p) + "%";
}
-);
+
+ function clamp(value, low, high) {
+ return Math.max(low, Math.min(high, value));
+ }
+
+ function copyBounds(bounds) {
+ return {
+ start: bounds.start,
+ end: bounds.end
+ };
+ }
+
+ /**
+ * Controller used by the `time-controller` template.
+ * @memberof platform/commonUI/general
+ * @constructor
+ * @param $scope the Angular scope for this controller
+ * @param {FormatService} formatService the service to user to format
+ * domain values
+ * @param {string} defaultFormat the format to request when no
+ * format has been otherwise specified
+ * @param {Function} now a function to return current system time
+ */
+ function TimeRangeController($scope, formatService, defaultFormat, now) {
+ this.$scope = $scope;
+ this.formatService = formatService;
+ this.defaultFormat = defaultFormat;
+ this.now = now;
+
+ this.tickCount = 2;
+ this.innerMinimumSpan = 1000; // 1 second
+ this.outerMinimumSpan = 1000; // 1 second
+ this.initialDragValue = undefined;
+ this.formatter = formatService.getFormat(defaultFormat);
+
+ this.$scope.ticks = [];
+
+ this.updateViewFromModel(this.$scope.ngModel);
+ this.updateFormModel();
+
+ [
+ 'updateViewFromModel',
+ 'updateSpanWidth',
+ 'updateOuterStart',
+ 'updateOuterEnd',
+ 'updateFormat',
+ 'validateStart',
+ 'validateEnd'
+ ].forEach(function (boundFn) {
+ this[boundFn] = this[boundFn].bind(this);
+ }, this);
+
+ this.$scope.$watchCollection("ngModel", this.updateViewFromModel);
+ this.$scope.$watch("spanWidth", this.updateSpanWidth);
+ this.$scope.$watch("ngModel.outer.start", this.updateOuterStart);
+ this.$scope.$watch("ngModel.outer.end", this.updateOuterEnd);
+ this.$scope.$watch("parameters.format", this.updateFormat);
+ }
+
+ TimeRangeController.prototype.formatTimestamp = function (ts) {
+ return this.formatter.format(ts);
+ };
+
+ TimeRangeController.prototype.updateTicks = function () {
+ var i, p, ts, start, end, span;
+ end = this.$scope.ngModel.outer.end;
+ start = this.$scope.ngModel.outer.start;
+ span = end - start;
+ this.$scope.ticks = [];
+ for (i = 0; i < this.tickCount; i += 1) {
+ p = i / (this.tickCount - 1);
+ ts = p * span + start;
+ this.$scope.ticks.push(this.formatTimestamp(ts));
+ }
+ };
+
+ TimeRangeController.prototype.updateSpanWidth = function (w) {
+ this.tickCount = Math.max(Math.floor(w / TICK_SPACING_PX), 2);
+ this.updateTicks();
+ };
+
+ TimeRangeController.prototype.updateViewForInnerSpanFromModel = function (
+ ngModel
+ ) {
+ var span = ngModel.outer.end - ngModel.outer.start;
+
+ // Expose readable dates for the knobs
+ this.$scope.startInnerText = this.formatTimestamp(ngModel.inner.start);
+ this.$scope.endInnerText = this.formatTimestamp(ngModel.inner.end);
+
+ // And positions for the knobs
+ this.$scope.startInnerPct =
+ toPercent((ngModel.inner.start - ngModel.outer.start) / span);
+ this.$scope.endInnerPct =
+ toPercent((ngModel.outer.end - ngModel.inner.end) / span);
+ };
+
+ TimeRangeController.prototype.defaultBounds = function () {
+ var t = this.now();
+ return {
+ start: t - 24 * 3600 * 1000, // One day
+ end: t
+ };
+ };
+
+
+ TimeRangeController.prototype.updateViewFromModel = function (ngModel) {
+ ngModel = ngModel || {};
+ ngModel.outer = ngModel.outer || this.defaultBounds();
+ ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
+
+ // Stick it back is scope (in case we just set defaults)
+ this.$scope.ngModel = ngModel;
+
+ this.updateViewForInnerSpanFromModel(ngModel);
+ this.updateTicks();
+ };
+
+ TimeRangeController.prototype.startLeftDrag = function () {
+ this.initialDragValue = this.$scope.ngModel.inner.start;
+ };
+
+ TimeRangeController.prototype.startRightDrag = function () {
+ this.initialDragValue = this.$scope.ngModel.inner.end;
+ };
+
+ TimeRangeController.prototype.startMiddleDrag = function () {
+ this.initialDragValue = {
+ start: this.$scope.ngModel.inner.start,
+ end: this.$scope.ngModel.inner.end
+ };
+ };
+
+ TimeRangeController.prototype.toMillis = function (pixels) {
+ var span =
+ this.$scope.ngModel.outer.end - this.$scope.ngModel.outer.start;
+ return (pixels / this.$scope.spanWidth) * span;
+ };
+
+ TimeRangeController.prototype.leftDrag = function (pixels) {
+ var delta = this.toMillis(pixels);
+ this.$scope.ngModel.inner.start = clamp(
+ this.initialDragValue + delta,
+ this.$scope.ngModel.outer.start,
+ this.$scope.ngModel.inner.end - this.innerMinimumSpan
+ );
+ this.updateViewFromModel(this.$scope.ngModel);
+ };
+
+ TimeRangeController.prototype.rightDrag = function (pixels) {
+ var delta = this.toMillis(pixels);
+ this.$scope.ngModel.inner.end = clamp(
+ this.initialDragValue + delta,
+ this.$scope.ngModel.inner.start + this.innerMinimumSpan,
+ this.$scope.ngModel.outer.end
+ );
+ this.updateViewFromModel(this.$scope.ngModel);
+ };
+
+ TimeRangeController.prototype.middleDrag = function (pixels) {
+ var delta = this.toMillis(pixels),
+ edge = delta < 0 ? 'start' : 'end',
+ opposite = delta < 0 ? 'end' : 'start';
+
+ // Adjust the position of the edge in the direction of drag
+ this.$scope.ngModel.inner[edge] = clamp(
+ this.initialDragValue[edge] + delta,
+ this.$scope.ngModel.outer.start,
+ this.$scope.ngModel.outer.end
+ );
+ // Adjust opposite knob to maintain span
+ this.$scope.ngModel.inner[opposite] =
+ this.$scope.ngModel.inner[edge] +
+ this.initialDragValue[opposite] -
+ this.initialDragValue[edge];
+
+ this.updateViewFromModel(this.$scope.ngModel);
+ };
+
+ TimeRangeController.prototype.updateFormModel = function () {
+ this.$scope.formModel = {
+ start: ((this.$scope.ngModel || {}).outer || {}).start,
+ end: ((this.$scope.ngModel || {}).outer || {}).end
+ };
+ };
+
+ TimeRangeController.prototype.updateOuterStart = function () {
+ var ngModel = this.$scope.ngModel;
+
+ ngModel.inner.start =
+ Math.max(ngModel.outer.start, ngModel.inner.start);
+ ngModel.inner.end = Math.max(
+ ngModel.inner.start + this.innerMinimumSpan,
+ ngModel.inner.end
+ );
+
+ this.updateFormModel();
+ this.updateViewForInnerSpanFromModel(ngModel);
+ this.updateTicks();
+ };
+
+ TimeRangeController.prototype.updateOuterEnd = function () {
+ var ngModel = this.$scope.ngModel;
+
+ ngModel.inner.end =
+ Math.min(ngModel.outer.end, ngModel.inner.end);
+ ngModel.inner.start = Math.min(
+ ngModel.inner.end - this.innerMinimumSpan,
+ ngModel.inner.start
+ );
+
+ this.updateFormModel();
+ this.updateViewForInnerSpanFromModel(ngModel);
+ this.updateTicks();
+ };
+
+ TimeRangeController.prototype.updateFormat = function (key) {
+ this.formatter = this.formatService.getFormat(key || this.defaultFormat);
+ this.updateViewForInnerSpanFromModel(this.$scope.ngModel);
+ this.updateTicks();
+ };
+
+ TimeRangeController.prototype.updateBoundsFromForm = function () {
+ var start = this.$scope.formModel.start,
+ end = this.$scope.formModel.end;
+ if (end >= start + this.outerMinimumSpan) {
+ this.$scope.ngModel = this.$scope.ngModel || {};
+ this.$scope.ngModel.outer = { start: start, end: end };
+ }
+ };
+
+ TimeRangeController.prototype.validateStart = function (startValue) {
+ return startValue <=
+ this.$scope.formModel.end - this.outerMinimumSpan;
+ };
+
+ TimeRangeController.prototype.validateEnd = function (endValue) {
+ return endValue >=
+ this.$scope.formModel.start + this.outerMinimumSpan;
+ };
+
+ return TimeRangeController;
+});
diff --git a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
index efff87651f..086947950a 100644
--- a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
+++ b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js
@@ -94,18 +94,18 @@ define(
it("exposes start time validator", function () {
var testValue = 42000000;
mockScope.formModel = { end: testValue };
- expect(mockScope.validateStart(testValue + 1))
+ expect(controller.validateStart(testValue + 1))
.toBe(false);
- expect(mockScope.validateStart(testValue - 60 * 60 * 1000 - 1))
+ expect(controller.validateStart(testValue - 60 * 60 * 1000 - 1))
.toBe(true);
});
it("exposes end time validator", function () {
var testValue = 42000000;
mockScope.formModel = { start: testValue };
- expect(mockScope.validateEnd(testValue - 1))
+ expect(controller.validateEnd(testValue - 1))
.toBe(false);
- expect(mockScope.validateEnd(testValue + 60 * 60 * 1000 + 1))
+ expect(controller.validateEnd(testValue + 60 * 60 * 1000 + 1))
.toBe(true);
});
@@ -134,7 +134,7 @@ define(
});
it("updates model bounds on request", function () {
- mockScope.updateBoundsFromForm();
+ controller.updateBoundsFromForm();
expect(mockScope.ngModel.outer.start)
.toEqual(mockScope.formModel.start);
expect(mockScope.ngModel.outer.end)
@@ -160,27 +160,27 @@ define(
});
it("updates the start time for left drags", function () {
- mockScope.startLeftDrag();
- mockScope.leftDrag(250);
+ controller.startLeftDrag();
+ controller.leftDrag(250);
expect(mockScope.ngModel.inner.start)
.toEqual(DAY * 1000 + HOUR * 9);
});
it("updates the end time for right drags", function () {
- mockScope.startRightDrag();
- mockScope.rightDrag(-250);
+ controller.startRightDrag();
+ controller.rightDrag(-250);
expect(mockScope.ngModel.inner.end)
.toEqual(DAY * 1000 + HOUR * 15);
});
it("updates both start and end for middle drags", function () {
- mockScope.startMiddleDrag();
- mockScope.middleDrag(-125);
+ controller.startMiddleDrag();
+ controller.middleDrag(-125);
expect(mockScope.ngModel.inner).toEqual({
start: DAY * 1000,
end: DAY * 1000 + HOUR * 18
});
- mockScope.middleDrag(250);
+ controller.middleDrag(250);
expect(mockScope.ngModel.inner).toEqual({
start: DAY * 1000 + HOUR * 6,
end: DAY * 1001
@@ -188,8 +188,8 @@ define(
});
it("enforces a minimum inner span", function () {
- mockScope.startRightDrag();
- mockScope.rightDrag(-9999999);
+ controller.startRightDrag();
+ controller.rightDrag(-9999999);
expect(mockScope.ngModel.inner.end)
.toBeGreaterThan(mockScope.ngModel.inner.start);
});