Browse Source

HUE-399. Allow HueChart to show time offsets rather than absolute dates

Marcus McLaughlin 15 years ago
parent
commit
092e77201a

+ 39 - 17
desktop/core/static/js/Source/Hue/HueChart.Box.js

@@ -39,7 +39,10 @@ HueChart.Box = new Class({
 				dates: {x: false, y: false}, //is the data in an axis a date ? 
 				dateSpans:{x: null}, //if an axis is a date, what time span should the tick marks for that axis be shown in
 				positionIndicator: false, //should the position indicator be shown ?
-				ticks: {x: false, y: false}, //should tick marks be shown ?
+				ticks: {x: false, y: false, orientation: 'absolute'}, //should tick marks be shown ?
+					//Orientation options are:
+						// 'absolute' -- meaning they are actual dates
+						// 'relative' -- meaning they are timespans from the first date
 				showLabels: false, //should axis labels be shown ?
 				tickColor: "#555", //the color of the tick marks
 				tickDateFormats: {
@@ -173,14 +176,42 @@ HueChart.Box = new Class({
 				};
 		},
 		
+		//Returns fn to control the tick label string
+		_getXTickDisplayFn: function(xTicks, tickOrientation, getXValue) {
+			//Function will return the correct xValue dependent on whether or not x is a date
+			//Define getTickLabel function based on possible states.
+			if (this.options.dates.x) {
+				var dateProperty = this.dateProperty;
+				//If these are absolute dates, just show the date and use the default getValue fn.
+				if (tickOrientation == 'absolute') {
+					var tickFormat = this.options.tickDateFormats[xTicks.unit];
+					return function(d) {
+						return d[dateProperty].format(tickFormat);
+					};
+				}
+				//If they are relative dates
+				if (tickOrientation == 'relative') {
+					return function(d) {
+						return d.label;
+					};
+				}
+			} else {
+				return function(d) {
+					return getXValue(d);
+				};
+			}
+		},
 		//Draw the X and Y tick marks.
 		setTicks:function(vis) {
+
 				if (this.options.ticks.x) {
 						//Add X-Ticks.
 						//Create tick array.
-						var xTicks = (this.options.dates.x ? this.getData(true).getTicks(10, this.dateProperty) : this.xScale.ticks(7));
-						//Function will return the correct xValue dependent on whether or not x is a date
-						var getXValue = getXValueFn(this.options.dates.x ? this.xProperty : null);
+						var tickOrientation = this.options.ticks.orientation;
+						var tickMethod = 'get' + tickOrientation.capitalize() + 'Ticks';
+						var xTicks = (this.options.dates.x ? this.getData(true)[tickMethod](10, this.dateProperty) : this.xScale.ticks(7));
+						var getValue = getXValueFn(this.options.dates.x ? this.xProperty : null);
+						var getTickLabel = this._getXTickDisplayFn(xTicks, tickOrientation, getValue);
 						//Create rules (lines intended to denote scale)
 						vis.add(pv.Rule)
 								//Use the tick array as data.
@@ -188,23 +219,14 @@ HueChart.Box = new Class({
 								//The bottom of the rule should be at the bottomPadding - the height of the rule.
 								.bottom(this.options.bottomPadding - this.options.xTickHeight)
 								//The left of the rule should be at the data object's xProperty value scaled to pixels.
-								.left(function(d) { return this.xScale(getXValue(d)); }.bind(this))
+								.left(function(d) { return this.xScale(getValue(d)); }.bind(this))
 								//Set the height of the rule to the xTickHeight
 								.height(this.options.xTickHeight)
 								.strokeStyle(this.options.tickColor)
 								//Add label to bottom of each rule
 								.anchor("bottom").add(pv.Label)
-										.text(function(d) {
-												//If the option is a date, format the date property field.
-												//Otherwise, simply show it.
-												if(this.options.dates.x) {
-														return d[this.dateProperty].format(this.options.tickDateFormats[xTicks.unit]);
-												} else {
-														return getXValue(d);
-												}
-										}.bind(this));
+										.text(function(d) { return getTickLabel(d);}.bind(this));
 				}
-				
 				if (this.options.ticks.y) {
 						//Add Y-Ticks
 						//Calculate number of yTicks to show.
@@ -227,7 +249,7 @@ HueChart.Box = new Class({
 								.strokeStyle(this.options.tickColor)
 								//Add label to the left which shows the number of bytes.
 								.anchor("left").add(pv.Label)
-										.text(function(d) { 
+										.text(function(d) {
 												if(this.options.yType == 'bytes') return d.convertFileSize();
 												return d;
 										}.bind(this));
@@ -236,7 +258,7 @@ HueChart.Box = new Class({
 		
 		//Add X and Y axis labels.
 		setLabels: function(vis) {
-				//Add Y-Label to center of chart. 
+				//Add Y-Label to center of chart.
 				vis.anchor("center").add(pv.Label)
 						.textAngle(-Math.PI/2)
 						.text(this.options.labels.y)

+ 29 - 2
desktop/core/static/js/Source/Hue/HueChart.js

@@ -365,21 +365,37 @@ HueChart.Data = new Class({
 		
 		
 		dataMsProperty: "ms",
+
+		getAbsoluteTicks: function(maxTickCount, dateProperty, startMs, endMs) {
+			return this._getTicks(maxTickCount, dateProperty, true, startMs, endMs);
+		},
+
+		getRelativeTicks: function(maxTickCount, dateProperty, startMs, endMs) {
+			return this._getTicks(maxTickCount, dateProperty, false, startMs, endMs);
+		},
+
 		/* getTicks --
 				Returns an array of data objects to be marked as ticks on the domain (x) axis.
 				Arguments:
 				maxTickCount (integer) - the upper bound on size of the return array
 				dateProperty (string) - the property which stores date objects
+				absolute (boolean) - determines whether the ticks are absolute values based on the time, or relative values indexed on the first time
 				startMs (integer) - milliseconds since some reference time
 				endMs (integer) - milliseconds since the same reference time
 		*/
-		getTicks: function(maxTickCount, dateProperty, startMs, endMs) {
+		_getTicks: function(maxTickCount, dateProperty, absolute, startMs, endMs) {
 			var maxIntervalCount = maxTickCount + 1;
+
 			
 			if (!$defined(startMs)) {
 				startMs = this.dataObjects[0][this.dataMsProperty];
 				endMs = this.dataObjects.getLast()[this.dataMsProperty];
 			}
+
+			if (!absolute) {
+				endMs = endMs - startMs;
+				startMs = 0;
+			}
 			
 			var domainMs = endMs - startMs;
 			var adjustedDomainMs, unit, unitMs, intervals, interval, intervalMs, tickObject;
@@ -404,7 +420,16 @@ HueChart.Data = new Class({
 				}
 			
 			var ticksMs = [];
-			
+			var getTickLabel = function(tickObj) {
+				var diffMs = tickObj[this.dataMsProperty] - startMs;
+				var numUnits = diffMs/unitMs;
+				return numUnits + " " + unit + (unit == 'ms' ? "" : numUnits > 1 ? "s" : "");
+			}.bind(this);
+
+			var makeRelative = function(tickObj) {
+				tickObj.label = getTickLabel(tickObj);
+				tickObj[this.dataMsProperty] += this.dataObjects[0][this.dataMsProperty];
+			}.bind(this);
 			if (i < uniformUnitsLength) {
 				// Broke free from uniform unit loop; selected unit has uniform intervals.
 				// Get tick marks with intervals aligned at 0 mod intervalMs
@@ -414,6 +439,7 @@ HueChart.Data = new Class({
 					tickObject = {};
 					tickObject[this.dataMsProperty] = tickMs;
 					tickObject[dateProperty] = tickDate;
+					if(!absolute) makeRelative(tickObject);
 					tickMs += intervalMs;
 					tickDate = tickDate.clone().increment('ms', intervalMs);
 					ticksMs.push(tickObject);
@@ -469,6 +495,7 @@ HueChart.Data = new Class({
 					dateMs = date.valueOf();
 					tickObject[this.dataMsProperty] = dateMs;
 					tickObject[dateProperty] = date.clone();
+					if (!absolute) makeRelative(tickObject);
 					ticksMs.push(tickObject);
 					date.increment(unit, interval);
 				} while (dateMs < endMs);