Application
{
backgroundGradientColors: #FFFFFF, #FFFFFF;
backgroundAlpha: 1;
}
AreaChart
{
gutterLeft: 0;
gutterRight: 0;
gutterTop: 0;
gutterBottom: 0;
}
.noAxisStyle
{
showLine: false;
showLabels: false;
tickPlacement: none;
}
.mainChartStyle
{
gutterBottom: 18;
gutterLeft: 0;
gutterRight: 0;
}
.canvasContainerStyles
{
borderThickness: 1;
borderColor: #333333;
borderStyle: solid;
backgroundColor: #FFFFFF;
backgroundAlpha: 1;
}
GridLines
{
horizontalChangeCount: 1;
verticalChangeCount: 2;
direction: both;
}
HDividedBox
{
borderThickness: 1;
borderColor: #CCCCCC;
borderStyle: solid;
}
LinkButton
{
paddingLeft: 0;
paddingRight: 0;
paddingTop: 0;
paddingBottom: 0;
}
Button
{
fillAlphas: 1,1;
cornerRadius: 2;
}
0 && allowUpdateComplete)
{
allowUpdateComplete = false;
updateBoxFromSlider = true;
updateBox();
this.visible = true;
}
}
/**
* Simple parsing function to convert the date strings in our dataset to the equivalent Date object.
*/
private function dateParse(value:String):Date
{
var dateArray:Array = value.split(' ');
var datePart:Array = dateArray[0].split('-');
var hourPart:Array = dateArray[1].split(':');
return new Date(datePart[0], datePart[1] - 1, datePart[2], hourPart[0],hourPart[1]);
}
/**
* Formats a date object from the DateTimeAxis into a label string
*/
private function formatDateLabel(value:Number, prevValue:Number, axis:DateTimeAxis):String
{
var dateValue:Date = new Date();
dateValue.setTime(value + ((dateValue.timezoneOffset + 60) * 60 * 1000));
switch(axis.labelUnits)
{
case "months":
return labelMonthFormatter.format(dateValue);
break;
case "days":
return labelDayFormatter.format(dateValue);
case "hours":
return labelHourFormatter.format(dateValue);
case "minutes":
return labelMinuteFormatter.format(dateValue);
default:
return labelDefaultFormatter.format(dateValue);
break;
}
}
/*Step 3 */
/**
* Called throughout use to update the mainData range of data that is displayed by slicing the
* range data to the left and right values.
*/
private function updateMainData():void
{
var delta:Number = rightIndicator.x - leftIndicator.x
//if (leftIndicator.x > rangeData.length-120){
//mainData.source = detailData.source.slice(0, detailData.length-1);
//datetimeaxis.dataUnits = "minutes"
//datetimeaxis.interval=5
//chartMouseOut();
//} else {
if (delta > 60){
datetimeaxis.dataUnits = "days"
} else {
datetimeaxis.dataUnits = "hours"
}
mainData.source = rangeData.source.slice(leftIndicator.x, rightIndicator.x);
chartMouseOut();
//}
}
/**
* Called from the slider value changes. It is filtered to only change when the slider calling it
* directly. The updateBoxFromSlider value is set to false when the moveSlider function effect is
* playing because the box widths have already been set by the dividerRelease calling
* updateIndicatorValuesWithEffect.
*/
private function updateBox():void
{
if(updateBoxFromSlider)
{
//setting the box width value to the slider value times the ratio (to decrease
//it to the equivalent width percentage
//eg. full divided box width = 500, rangeDataRatio = 1/5 would equal 100 for the
//proper left box width equal to range index value
leftBox.width = slider.values[0] * rangeDataRatio;
rightBox.width = dividedBox.width - ( slider.values[1] * rangeDataRatio );
leftIndicator.x = slider.values[0];
rightIndicator.x = slider.values[1];
updateMainData();
}
}
/**
* Updates the range by moving the entire range left or right by a fixed number of units
*/
private function clickUpdate(value:int):void
{
leftIndicator.x += value; rightIndicator.x += value;
slider.dispatchEvent(new SliderEvent('change'));
}
/**
* Called from the divided box dividerRelease. Calls a Move for the left and right Indicator
* x values which has an easing function
* applied.
*/
private function updateIndicatorValuesWithEffect():void
{
//setting indicator positions to the box width divided by the ratio (to increase
//it to the equivalent range value)
//eg. left box width = 100, rangeDataRation = 1/5 would equal 500 for the range index value
moveSlider(leftIndicator, (leftBox.width / rangeDataRatio), false);
moveSlider(rightIndicator, ((dividedBox.width - rightBox.width) / rangeDataRatio), false);
}
/**
* Called from the thumbRelease on the slider instance, as well as creationComplete
* to set the initial range values.
* Updates the left and right indicator x values without the move effect.
*/
private function updateIndicatorsQuietly():void
{
//these two values are mapped 1:1 as the slider values and indicator values equal the rangeData length exactly
leftIndicator.x = slider.values[0];
rightIndicator.x = slider.values[1];
}
/**
* Moves the left and right indicator x values with an easing transition applied. update
* dictates whether this should update the divided box range measurements (false if we're calling this
* from the divided box release) callbackFunc can be passed to get called when the move is finished.
*/
private function moveSlider(target:VRule, xTo:Number, update:Boolean, callbackFunc:Function = null, ... rest):void
{
var moveIndicator:Move = new Move();
moveIndicator.end();
moveIndicator.easingFunction = Cubic.easeOut;
moveIndicator.duration = 750;
moveIndicator.target = target;
moveIndicator.xTo = xTo;
moveIndicator.addEventListener(EffectEvent.EFFECT_START, function():void {updateBoxFromSlider = update});
moveIndicator.addEventListener(TweenEvent.TWEEN_UPDATE, function():void { mainData.source = rangeData.source.slice(leftIndicator.x, rightIndicator.x);
});
moveIndicator.addEventListener(EffectEvent.EFFECT_END, function():void {updateBoxFromSlider = true;
if(callbackFunc != null) callbackFunc.call(this, rest)});
moveIndicator.play();
}
/**
* Called from range chart or main chart and determines the position of the mouse as well as left
* and right indicators (for static comparison when moving) and adds systemManager events
* to capture mouse movement. The values set here are used in the moveChart function to calculate
* new position differences with start position
*/
private function setMouseDown(theChart:CartesianChart):void
{
//don't capture for drag if we're viewing the entire range of data
if(!(leftIndicator.x == 0 && rightIndicator.x == rangeData.length))
{
mouseXRef = this.mouseX;
staticLeftBoundary = leftIndicator.x;
staticRightBoundary = rightIndicator.x;
if(theChart == mainChart) mainDrag = true;
if(theChart == rangeChart) rangeDrag = true;
this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, moveChart);
this.systemManager.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
}
/**
* Called when systemManager receives mouseUp event. Sets the indicators for which range is
* being dragged to false, and removes the system manager event listeners for drag movement.
*/
private function stopDragging(event:MouseEvent):void
{
if(mainData.length < 2)
{
if(leftIndicator.x == rangeData.length)
{
leftIndicator.x = rangeData.length - 5;
rightIndicator.x = rangeData.length;
}
else if(rightIndicator.x == 0)
{
leftIndicator.x = 0;
rightIndicator.x = 5;
}
updateBox();
}
rangeDrag = false;
mainDrag = false;
this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, moveChart);
this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
/**
* Determines which chart instance is being dragged, and updates the left and right indicator x values
*/
private function moveChart(event:MouseEvent):void
{
if(mainDrag)
{
leftIndicator.x = staticLeftBoundary + (mouseXRef - this.mouseX) /
(mainChartArea.width / mainData.length);
rightIndicator.x = staticRightBoundary + (mouseXRef - this.mouseX) /
(mainChartArea.width / mainData.length);
}
else if(rangeDrag)
{
leftIndicator.x = staticLeftBoundary - (mouseXRef - this.mouseX) / rangeDataRatio;
rightIndicator.x = staticRightBoundary - (mouseXRef - this.mouseX) / rangeDataRatio;
}
}
/* Step 4 */
/**
* Finds the DateTimeAxis value (the date) of the mouseover position
*/
private function getChartDataPoint():void
{
}
/**
* Called when cursor is moved off of main chart area. Clears any values that are bound
* to mouseover position, and clears all
* LineSeriesCustomRenderers on the chart that are showing
*/
private function chartMouseOut():void
{
if(mainData.length > 2)
{
for(var i:int = 0; i < mainData.length; i++)
{
try
{
mainChart.series[0].getChildAt(i + 1).showRenderer(false);
mainChartVolume.series[0].getChildAt(i).showRenderer(false);
}
catch(e:Error) {};
}
_selectedDate = labelSummaryDateFormatter.format(dateParse(mainData.getItemAt(0).date)) + ' - ' +
labelSummaryDateFormatter.format(dateParse(mainData.getItemAt(mainData.length - 1).date));
}
else
{
_selectedDate = '';
}
}
/**
* Finds the DateTimeAxis value (the date) of the mouseover position
* invertTransform takes a point in stage space (x and y coordinate) and transforms it into the
* relative point in data space, giving appropriate values along x axis (first item in return array),
* and y axis (second item in return array)
*/
private function getChartCoordinates(thePos:Point, theChart:CartesianChart):Object
{
var tmpArray:Array;
if(theChart.series[0] != null)
{
tmpArray = theChart.series[0].dataTransform.invertTransform(thePos.x, thePos.y);
return {x:tmpArray[0], y:tmpArray[1]};
}
else
{
return null;
}
}
/**
* Updates the date range display to reflect the current position of the divided box drag
*/
private function setDividerDragDate():void
{
var tmpLeftIndex:int = leftBox.width / rangeDataRatio;
var tmpRightIndex:int = ((dividedBox.width - rightBox.width) / rangeDataRatio) - 1;
if(tmpLeftIndex >= 0 && tmpRightIndex <= rangeData.length)
{
_selectedDate = labelSummaryDateFormatter.format(dateParse(rangeData.getItemAt(tmpLeftIndex).date)) + ' - ' +
labelSummaryDateFormatter.format(dateParse(rangeData.getItemAt(tmpRightIndex).date));
}
}
/*Step 5 */
/**
* Prevents rollover or selection effects in the list control
*/
private function myEasingFunction(t:Number, b:Number, c:Number, d:Number):Number
{
return 0;
}
]]>