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);
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
{
trace("Updating mainData");
trace("lIndicator: " + leftIndicator.x)
trace("rIndicator: " + rightIndicator.x)
var lI:Number = indexMap(leftIndicator.x)
var rI:Number = indexMap(rightIndicator.x)
trace("lI: " + lI)
trace("rI: " + rI)
mainData.source = rangeData.source.slice(lI, rI);
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)
{
trace("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];
//leftIndicator.x = indexMap(slider.values[0]);
//rightIndicator.x = indexMap(slider.values[1]);
trace("S[0]: " + slider.values[0] + "--> " + leftIndicator.x);
trace("S[1]: " + slider.values[1] + "--> " + rightIndicator.x);
updateMainData();
}
}
private function indexMap(x:Number):int
{
trace("indexMap");
var pm:Number = rangeData.length
trace("pm =" + pm)
var x1:Number = (26/27)*pm
var x2:Number = pm
var y1:Number = 24*26
var y2:Number = 24*26+24*60
if (x < x1){
trace(x + " --->" + (y1/x1)*x)
return (y1/x1)*x
} else {
var m:Number = (y2-y1)/(x2-x1);
var b:Number = (x2*y1-x1*y2)/(x2-x1)
trace(x + " --->" + m*x+b)
return m*x+b
}
}
/**
* 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 {
updateMainData();
});
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
{
//filtering to only run if the full dataset is present in the chart...
//this value is false if the indicator move effect is playing
if(updateBoxFromSlider)
{
var chartPoint:Object = getChartCoordinates(new Point(mainChart.mouseX, mainChart.mouseY), mainChart);
var formattedDate:String = fullDateFormat.format(new Date(chartPoint.x));
for(var i:int = 0; i < mainData.length; i++)
{
var dataItem:Object = mainData.getItemAt(i);
if(dataItem.date == formattedDate)
{
_selectedDate = labelSummaryDateFormatter.format(dateParse(dataItem.date));
_selectedClose = 'Price: ' + dollarFormatter.format(Number(dataItem.close));
mainChart.series[0].getChildAt(i + 1).showRenderer(true);
}
else
{
mainChart.series[0].getChildAt(i + 1).showRenderer(false);
}
}
}
}
/**
* 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));
_selectedClose = percentageFormatter.format((Number(mainData.getItemAt(mainData.length - 1).close) /
Number(mainData.getItemAt(0).close) - 1) * 100) + '%';
}
else
{
_selectedDate = '';
_selectedClose = '';
}
}
/**
* 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));
_selectedClose = percentageFormatter.format((Number(rangeData.getItemAt(tmpRightIndex).close) /
Number(rangeData.getItemAt(tmpLeftIndex).close) - 1) * 100) + '%';
}
}
/*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;
}
]]>