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 ? 
 				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
 				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 ?
 				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 ?
 				showLabels: false, //should axis labels be shown ?
 				tickColor: "#555", //the color of the tick marks
 				tickColor: "#555", //the color of the tick marks
 				tickDateFormats: {
 				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.
 		//Draw the X and Y tick marks.
 		setTicks:function(vis) {
 		setTicks:function(vis) {
+
 				if (this.options.ticks.x) {
 				if (this.options.ticks.x) {
 						//Add X-Ticks.
 						//Add X-Ticks.
 						//Create tick array.
 						//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)
 						//Create rules (lines intended to denote scale)
 						vis.add(pv.Rule)
 						vis.add(pv.Rule)
 								//Use the tick array as data.
 								//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.
 								//The bottom of the rule should be at the bottomPadding - the height of the rule.
 								.bottom(this.options.bottomPadding - this.options.xTickHeight)
 								.bottom(this.options.bottomPadding - this.options.xTickHeight)
 								//The left of the rule should be at the data object's xProperty value scaled to pixels.
 								//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
 								//Set the height of the rule to the xTickHeight
 								.height(this.options.xTickHeight)
 								.height(this.options.xTickHeight)
 								.strokeStyle(this.options.tickColor)
 								.strokeStyle(this.options.tickColor)
 								//Add label to bottom of each rule
 								//Add label to bottom of each rule
 								.anchor("bottom").add(pv.Label)
 								.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) {
 				if (this.options.ticks.y) {
 						//Add Y-Ticks
 						//Add Y-Ticks
 						//Calculate number of yTicks to show.
 						//Calculate number of yTicks to show.
@@ -227,7 +249,7 @@ HueChart.Box = new Class({
 								.strokeStyle(this.options.tickColor)
 								.strokeStyle(this.options.tickColor)
 								//Add label to the left which shows the number of bytes.
 								//Add label to the left which shows the number of bytes.
 								.anchor("left").add(pv.Label)
 								.anchor("left").add(pv.Label)
-										.text(function(d) { 
+										.text(function(d) {
 												if(this.options.yType == 'bytes') return d.convertFileSize();
 												if(this.options.yType == 'bytes') return d.convertFileSize();
 												return d;
 												return d;
 										}.bind(this));
 										}.bind(this));
@@ -236,7 +258,7 @@ HueChart.Box = new Class({
 		
 		
 		//Add X and Y axis labels.
 		//Add X and Y axis labels.
 		setLabels: function(vis) {
 		setLabels: function(vis) {
-				//Add Y-Label to center of chart. 
+				//Add Y-Label to center of chart.
 				vis.anchor("center").add(pv.Label)
 				vis.anchor("center").add(pv.Label)
 						.textAngle(-Math.PI/2)
 						.textAngle(-Math.PI/2)
 						.text(this.options.labels.y)
 						.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",
 		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 --
 		/* getTicks --
 				Returns an array of data objects to be marked as ticks on the domain (x) axis.
 				Returns an array of data objects to be marked as ticks on the domain (x) axis.
 				Arguments:
 				Arguments:
 				maxTickCount (integer) - the upper bound on size of the return array
 				maxTickCount (integer) - the upper bound on size of the return array
 				dateProperty (string) - the property which stores date objects
 				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
 				startMs (integer) - milliseconds since some reference time
 				endMs (integer) - milliseconds since the same 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;
 			var maxIntervalCount = maxTickCount + 1;
+
 			
 			
 			if (!$defined(startMs)) {
 			if (!$defined(startMs)) {
 				startMs = this.dataObjects[0][this.dataMsProperty];
 				startMs = this.dataObjects[0][this.dataMsProperty];
 				endMs = this.dataObjects.getLast()[this.dataMsProperty];
 				endMs = this.dataObjects.getLast()[this.dataMsProperty];
 			}
 			}
+
+			if (!absolute) {
+				endMs = endMs - startMs;
+				startMs = 0;
+			}
 			
 			
 			var domainMs = endMs - startMs;
 			var domainMs = endMs - startMs;
 			var adjustedDomainMs, unit, unitMs, intervals, interval, intervalMs, tickObject;
 			var adjustedDomainMs, unit, unitMs, intervals, interval, intervalMs, tickObject;
@@ -404,7 +420,16 @@ HueChart.Data = new Class({
 				}
 				}
 			
 			
 			var ticksMs = [];
 			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) {
 			if (i < uniformUnitsLength) {
 				// Broke free from uniform unit loop; selected unit has uniform intervals.
 				// Broke free from uniform unit loop; selected unit has uniform intervals.
 				// Get tick marks with intervals aligned at 0 mod intervalMs
 				// Get tick marks with intervals aligned at 0 mod intervalMs
@@ -414,6 +439,7 @@ HueChart.Data = new Class({
 					tickObject = {};
 					tickObject = {};
 					tickObject[this.dataMsProperty] = tickMs;
 					tickObject[this.dataMsProperty] = tickMs;
 					tickObject[dateProperty] = tickDate;
 					tickObject[dateProperty] = tickDate;
+					if(!absolute) makeRelative(tickObject);
 					tickMs += intervalMs;
 					tickMs += intervalMs;
 					tickDate = tickDate.clone().increment('ms', intervalMs);
 					tickDate = tickDate.clone().increment('ms', intervalMs);
 					ticksMs.push(tickObject);
 					ticksMs.push(tickObject);
@@ -469,6 +495,7 @@ HueChart.Data = new Class({
 					dateMs = date.valueOf();
 					dateMs = date.valueOf();
 					tickObject[this.dataMsProperty] = dateMs;
 					tickObject[this.dataMsProperty] = dateMs;
 					tickObject[dateProperty] = date.clone();
 					tickObject[dateProperty] = date.clone();
+					if (!absolute) makeRelative(tickObject);
 					ticksMs.push(tickObject);
 					ticksMs.push(tickObject);
 					date.increment(unit, interval);
 					date.increment(unit, interval);
 				} while (dateMs < endMs);
 				} while (dateMs < endMs);