package mx.collections {
import flash.events.TimerEvent;
import flash.utils.Dictionary;
import flash.utils.Timer;
import mx.collections.errors.ItemPendingError;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.CubeEvent;
use namespace mx_internal;
[DefaultProperty("grouping")]
/**
* The GroupingCollection class lets you create grouped data from flat data
* for display in the AdvancedDataGrid control.
* When you create the instance of the GroupingCollection from your flat data,
* you specify the field or fields of the data used to create the hierarchy.
*
* <p>To populate the AdvancedDataGrid control with grouped data,
* you create an instance of the GroupingCollection class from your flat data,
* and then pass that GroupingCollection instance to the data provider
* of the AdvancedDataGrid control.
* To specify the grouping fields of your flat data,
* you pass a Grouping instance to
* the <code>GroupingCollection.grouping</code> property.
* The Grouping instance contains an Array of GroupingField instances,
* one per grouping field. </p>
*
* <p>The following example uses the GroupingCollection class to define
* two grouping fields: Region and Territory.</p>
*
* <pre>
* <mx:AdvancedDataGrid id="myADG"
* <mx:dataProvider>
* <mx:GroupingCollection id="gc" source="{dpFlat}">
* <mx:grouping>
* <mx:Grouping>
* <mx:GroupingField name="Region"/>
* <mx:GroupingField name="Territory"/>
* </mx:Grouping>
* </mx:grouping>
* </mx:GroupingCollection>
* </mx:dataProvider>
*
* <mx:columns>
* <mx:AdvancedDataGridColumn dataField="Region"/>
* <mx:AdvancedDataGridColumn dataField="Territory"/>
* <mx:AdvancedDataGridColumn dataField="Territory_Rep"/>
* <mx:AdvancedDataGridColumn dataField="Actual"/>
* <mx:AdvancedDataGridColumn dataField="Estimate"/>
* </mx:columns>
* </mx:AdvancedDataGrid>
* </pre>
*
* @mxml
*
* The <code><mx.GroupingCollection></code> inherits all the tag attributes of its superclass,
* and defines the following tag attributes:</p>
*
* <pre>
* <mx:GroupingCollection
* <b>Properties </b>
* grouping="<i>No default</i>"
* source="<i>No default</i>"
* summaries="<i>No default</i>"
* />
* </pre>
*
* @see mx.controls.AdvancedDataGrid
* @see mx.collections.Grouping
* @see mx.collections.GroupingField
*/
[Event(name="progress", type="mx.events.CubeEvent")]
[Event(name="complete", type="mx.events.CubeEvent")]
public class GroupingCollection1 extends HierarchicalData implements IGroupingCollection
{
/**
* Constructor.
*/
public function GroupingCollection1()
{
super();
newCollection = new ArrayCollection();
super.source = newCollection;
objectSummaryMap = new Dictionary(false);
parentMap = {};
}
/**
* @private
*
* denotes if the refresh is asynchronous.
*/
private var async:Boolean = false;
/**
* @private
*/
private var newCollection:ArrayCollection;
/**
* @private
*/
private var _sourceCol:ICollectionView;
/**
* @private
*
* the object summary map.
* keeps summaries corresponding to different objects
*/
private var objectSummaryMap:Dictionary;
/**
* @private
*
* the original sort applied to the source collection
*/
private var oldSort:Sort;
/**
* The timer which is associated with an asynchronous refresh operation.
* You can use it to change the timing interval, pause the refresh,
* or perform other actions.
*
* The default value for the <code>delay</code> property of the
* Timer instance is 1, corresponding to 1 millisecond.
*
*/
protected var timer:Timer;
/**
* @private
*/
private var prepared:Boolean = false;
/**
* @private
*/
private var flatView:ICollectionView;
/**
* @private
*/
private var flatCursor:IViewCursor;
/**
* @private
*/
/**
* @private
*/
private var treeCursor:IViewCursor;
/**
* @private
*/
private var currentPosition:CursorBookmark = CursorBookmark.FIRST;
/**
* @private
*/
private var gf:Array;
/**
* @private
*/
private var fieldCount:int;
/**
* @private
*
* contains current data being compared
*/
private var currentData:Object;
/**
* @private
*
* contains current group objects for different group fields
*/
private var currentGroups:Array;
/**
* @private
*
* contains current group labels for different group fields
*/
private var currentGroupLabels:Array;
/**
* @private
*
* contains next index for different group fields
*/
private var currentIndices:Array;
/**
* @private
*
* item index
*/
private var itemIndex:int;
/**
* @private
*
* the children array for the group
*/
private var childrenArray:Array;
/**
* @private
* Mapping of UID to parents. Must be maintained as things get removed/added
* This map is created as objects are visited
*/
protected var parentMap:Object;
/**
* @private
*/
mx_internal var optimizeSummaries:Boolean = false;
/**
* @private
*/
private var summaryPresent:Boolean;
/**
* Array of SummaryRow instances that define any root-level data summaries.
* Specify one or more SummaryRow instances to define the data summaries,
* as the following example shows:
*
* <pre>
* <mx:AdvancedDataGrid id="myADG"
* width="100%" height="100%"
* initialize="gc.refresh();">
* <mx:dataProvider>
* <mx:GroupingCollection id="gc" source="{dpFlat}">
* <mx:summaries>
* <mx:SummaryRow summaryPlacement="last">
* <mx:fields>
* <mx:SummaryField dataField="Actual"
* label="Min Actual" operation="MIN"/>
* <mx:SummaryField dataField="Actual"
* label="Max Actual" operation="MAX"/>
* </mx:fields>
* </mx:SummaryRow>
* </mx:summaries>
* <mx:Grouping>
* <mx:GroupingField name="Region"/>
* <mx:GroupingField name="Territory"/>
* </mx:Grouping>
* </mx:GroupingCollection>
* </mx:dataProvider>
*
* <mx:columns>
* <mx:AdvancedDataGridColumn dataField="Region"/>
* <mx:AdvancedDataGridColumn dataField="Territory_Rep"
* headerText="Territory Rep"/>
* <mx:AdvancedDataGridColumn dataField="Actual"/>
* <mx:AdvancedDataGridColumn dataField="Estimate"/>
* <mx:AdvancedDataGridColumn dataField="Min Actual"/>
* <mx:AdvancedDataGridColumn dataField="Max Actual"/>
* </mx:columns>
* </mx:AdvancedDataGrid></pre>
*
* @see mx.collections.SummaryRow
* @see mx.collections.SummaryField
*/
public var summaries:Array;
private var _grouping:Grouping;
/**
* Specifies the Grouping instance applied to the source data.
* Setting the <code>grouping</code> property
* does not automatically refresh the view,
* so you must call the <code>refresh()</code> method
* after setting this property.
*
* @see mx.collections.GroupingCollection#refresh()
*/
public function get grouping():Grouping
{
return _grouping;
}
/**
* @private
*/
public function set grouping(value:Grouping):void
{
_grouping = value;
}
/**
* The source collection containing the flat data to be grouped.
*
* If the source is not a collection, it will be auto-wrapped into a collection.
*
*/
override public function get source():Object
{
return _sourceCol;
}
override public function set source(value:Object):void
{
if (!value)
{
_sourceCol = null;
return;
}
_sourceCol = ICollectionView(value);
}
/**
* @private
*/
/**
* Return <code>super.source</code>, if the <code>grouping</code> property is set,
* and an ICollectionView instance that refers to <code>super.source</code> if not.
*
* @return The object to return.
*/
override public function getRoot():Object
{
return super.source;
}
/**
* @inheritDoc
*/
public function refresh(async:Boolean = false):Boolean
{
this.async = async;
var resetEvent:CollectionEvent;
if (!grouping || grouping.fields.length < 1 )
{
super.source = source;
resetEvent =
new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
resetEvent.kind = CollectionEventKind.RESET;
dispatchEvent(resetEvent);
buildGroups(); return true;
}
super.source = newCollection;
resetEvent =
new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
resetEvent.kind = CollectionEventKind.RESET;
dispatchEvent(resetEvent);
parentMap = {};
objectSummaryMap = new Dictionary(false);
summaryPresent = false;
for (var i:int = 0; i < grouping.fields.length; i++)
{
if (GroupingField(grouping.fields[i]).summaries)
{
summaryPresent = true;
break;
}
}
var grouped:Boolean;
if(source && grouping)
{
grouped = makeGroupedCollection();
}
return grouped;
}
/**
* @inheritDoc
*/
public function cancelRefresh():void
{
if (timer)
{
timer.stop();
timer = null;
cleanUp();
}
}
/**
* @private
*
* check for the existing groups if they can accomodate the item
* otherwise create new group and place the item.
*/
/**
* @private
*
* check for existence of the groups for an item in the collection
* and return all the parent of that item.
*/
/**
* @private
*
* collection change handler.
*
*/
/**
* @private
*
* creating the group for the item in the collection
* and placing it there.
*/
/**
* @private
*
* returns the collection view of the given object
*/
/**
* @private
* get the data label from user specified function.
* otherwise get the label from the data.
*/
private function getDataLabel(data:Object,field:GroupingField):String
{
if (field.groupingFunction != null)
return field.groupingFunction(data, field);
return data.hasOwnProperty(field.name) ? data[field.name] : "Not Available";
}
/**
* Returns the parent of a node.
* The parent of a top-level node is <code>null</code>.
*
* @param node The Object that defines the node.
*
* @return The parent node containing the node as child,
* <code>null</code> for a top-level node,
* and <code>undefined</code> if the parent cannot be determined.
*/
/**
* @private
*
* generate the root summaries.
* different for flat data and grouped data.
*
*/
/**
* @private
*
* calculate the summaries for a given parent,
* populate the objectSummaryMap and
* insert the summary in the collection
*
*/
/**
* @private
*
* computes the summary for the parent node.
* will fetch the summaries from the object summary map
*
*/
/**
* @private
*
* calculates the summary by traversing over the iterator.
*
*/
/**
* @private
*
* initialize the variables
*
*/
private function initialize():void
{
currentData = null;
currentGroups = [];
currentGroupLabels = [];
currentIndices = [] ;
childrenArray = null;
_generatedRootSummaries = [];
if(source==null){
source = new ArrayCollection;
}
if (source && summaries){ _generatedRootSummaries = [];
for (var i:int = 0; i < summaries.length; i++) {
_generatedRootSummaries[i] = new SummaryObject(); for each(var summaryField:SummaryField in SummaryRow(summaries[i]).fields) {
if(summaryField.operation == 'STRINGAGG'){
/** Alphanumeric */
} else {
/** Numeric*/
if(summaryField.operation == 'MIN'){
_generatedRootSummaries[i][summaryField.dataField] = Number.MAX_VALUE; } else if(summaryField.operation == 'MAX'){
_generatedRootSummaries[i][summaryField.dataField] = Number.MIN_VALUE; } else {
_generatedRootSummaries[i][summaryField.dataField] = 0.0; }
}
}
}
}
}
/**
* @private
*
* insert the root summaries
*
*/
/**
* @private
*
* inserts the summaries in the children collection of the parent node
*/
private function insertSummary(parent:Object, summaryObj:Array, summaries:Array):void
{
for (var i:int = 0; i < summaries.length ; i++)
{
var summaryRow:SummaryRow = summaries[i];
if (summaryRow.summaryPlacement.indexOf("group") != -1)
{
for (var str:String in summaryObj[i])
parent[str] = summaryObj[i][str];
}
var children:IList;
if (summaryRow.summaryPlacement.indexOf("first") != -1)
{
children = (getChildren(parent) as ArrayCollection);
if (children)
children.addItemAt(summaryObj[i], 0);
}
if (summaryRow.summaryPlacement.indexOf("last") != -1)
{
children = (getChildren(parent) as ArrayCollection);
if (children)
children.addItem(summaryObj[i]);
}
}
}
/**
* @private
*/
private function makeGroupedCollection():Boolean
{
var fields:Array = [];
for (var i:int = 0; i < grouping.fields.length; i++)
{
var groupingField:GroupingField = grouping.fields[i];
var sortField:SortField = new SortField(groupingField.name,
groupingField.caseInsensitive,
groupingField.descending, groupingField.numeric);
sortField.compareFunction = groupingField.compareFunction;
fields.push(sortField);
}
oldSort = source.sort;
source.sort = new Sort();
if (grouping.compareFunction != null)
source.sort.compareFunction = grouping.compareFunction;
source.sort.fields = fields;
var refreshed:Boolean = source.refresh();
if (!refreshed)
return refreshed;
if (async)
{
timer = new Timer(1);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
}
else
{
return buildGroups();
}
return true;
}
/**
* @private
*/
private function timerHandler(event:TimerEvent):void
{
if (buildGroups())
{
timer.stop();
timer = null;
}
}
/**
* @private
*
* Start building the groups
*/
[Bindable]public var progress:int = 0;
private function buildGroups():Boolean {
if (!prepared){
var _openItems:Object = {};
initialize();
newCollection.removeAll();
if ((source as ICollectionView).length == 0)
return false;
flatView = source as ICollectionView;
flatCursor = flatView.createCursor();
gf = grouping?grouping.fields:[];
fieldCount = gf.length;
if (gf){
prepared = true;
if (async){
return false;
} }
if (async){
return true;
} }
flatCursor.seek(currentPosition);
while(!flatCursor.afterLast && currentPosition != CursorBookmark.LAST) {
progress = Math.max(1,1+currentPosition.getViewIndex());
dispatchProgress(progress, source.length,"Processing data Row: " + progress + " of " + source.length );
currentData = flatCursor.current;
if (source && summaries){ calculateRootSummariesLOOP(currentData);
}
for (var i:int = 0; i < fieldCount ; ++i) {
var groupingField:String = gf[i].name;
var label:String = getDataLabel(currentData, gf[i]);
if(label != currentGroupLabels[i])
{
if (childrenArray && childrenArray.length)
{
ArrayCollection(currentGroups[fieldCount - 1][childrenField]).source = childrenArray;
calculateSummariesEND(grouping.fields[i].summaries,i,currentData,childrenArray);
childrenArray = [];
if (async)
return false;
}
currentGroupLabels.splice(i+1);
currentGroups.splice(i+1);
currentIndices.splice(i+1);
currentGroupLabels[i] = label;
if (gf[i].groupingObjectFunction != null)
currentGroups[i] = gf[i].groupingObjectFunction(label);
else if (grouping.groupingObjectFunction != null)
currentGroups[i] = grouping.groupingObjectFunction(label);
else
currentGroups[i] = {};
if(grouping.fields[i].summaries){
currentGroups[i]['summaryObjArry'] = [];
for (var k:int = 0; k < grouping.fields[i].summaries.length; k++) {
currentGroups[i]['summaryObjArry'][k] = new SummaryObject(); }
}
currentGroups[i][childrenField] = new ArrayCollection();
currentGroups[i][grouping.label] = currentGroupLabels[i];
itemIndex = currentIndices[i-1];
if (i > 0){
currentGroups[(i - 1)][childrenField].source.push(currentGroups[i]);
} else {
newCollection.source.push(currentGroups[i]);
}
currentIndices[i-1] = ++itemIndex;
}
if ( i == fieldCount - 1)
{
itemIndex = currentIndices[i];
if (!childrenArray)
childrenArray = [];
childrenArray.push(currentData);
currentIndices[i] = ++itemIndex;
}
calculateSummariesLOOP(grouping.fields[i].summaries,i,currentData,childrenArray);
}
try
{
flatCursor.moveNext();
currentPosition = flatCursor.bookmark;
}
catch (pending:ItemPendingError)
{
cleanUp();
pending.addResponder(new ItemResponder(
function(data:Object, token:Object=null):void
{
makeGroupedCollection();
},
function(info:Object, token:Object=null):void
{
}));
}
}
if(super.source){
super.source.refresh();
}
if (source && summaries){ calculateRootSummariesEND();
}
dispatchEvent(new CubeEvent(CubeEvent.CUBE_COMPLETE));
if (currentPosition == CursorBookmark.LAST)
{
if (childrenArray && childrenArray.length)
{
ArrayCollection(currentGroups[fieldCount - 1][childrenField]).source = childrenArray;
calculateSummariesEND(grouping.fields[fieldCount - 1].summaries,fieldCount - 1,currentData,childrenArray);
}
var refreshEvent:CollectionEvent =
new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
refreshEvent.kind = CollectionEventKind.REFRESH;
dispatchEvent(refreshEvent);
cleanUp();
return true;
}
return true;
}
/**
* @private
*
* Restores the original sort in the source collection
* and clean up all the variables.
*/
private function cleanUp():void
{
source.sort = oldSort;
source.refresh();
prepared = false;
currentPosition = CursorBookmark.FIRST;
progress = currentPosition.getViewIndex();
oldSort = null;
flatCursor = null;
treeCursor = null;
}
/**
* @private
*
* It will call the function func on each node of the collection.
*/
/**
* @private
*
* removes the root summaries and
* generates them again.
*
*/
/**
* @private
*
* removes all the summaries from the collection
*/
/**
* @private
*
* remove the summaries for an item and its parents.
* return the parents of the node going one level up each time.
*
*/
/**
* @private
*
* removes the summaries from the parent node and all its children.
*
*/
/**
* @private
*
* Default implementation for operations - "SUM", "MIN", "MAX", "COUNT"
*/
/**
* @private
*
* updates the parent map
*/
/**
* @private
*
* removes the summary information and regenrates it for a particular node
* and its parents.
* optionally removes the item from the group also.
*/
/********************************************************************************************************/
private function dispatchProgress(p:int, t:int, m:String=null):void{
var ev:CubeEvent = new CubeEvent(CubeEvent.CUBE_PROGRESS);
ev.progress = p;
ev.total = t;
ev.message = m;
dispatchEvent(ev);
}
private function calculateSummariesEND(summaries:Array,depth:int,current:Object,childrenArry:Array):void {
if (depth > grouping.fields.length-1)
return;
if (!summaries)
return;
for (var i:int = 0; i < summaries.length; i++) {
for each(var summaryField:SummaryField in SummaryRow(summaries[i]).fields) {
/** Numeric*/
if(summaryField.operation == 'AVG'){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] /= currentGroups[depth]['summaryObjArry'][i][summaryField.dataField+'KOUNT'];
} }
insertSummary(currentGroups[depth],currentGroups[depth]['summaryObjArry'], summaries);
}
}
private function calculateSummariesLOOP(summaries:Array,depth:int,current:Object,childrenArry:Array):void {
if (depth > grouping.fields.length-1)
return;
if (!summaries)
return;
for (var i:int = 0; i < summaries.length; i++) {
for each(var summaryField:SummaryField in SummaryRow(summaries[i]).fields) {
if(summaryField.operation == 'STRINGAGG'){
/** Alphanumeric */
var newVal:String = current[summaryField.dataField];
var existingVal:String = currentGroups[depth]['summaryObjArry'][i][summaryField.dataField];
if(existingVal){
if(existingVal.indexOf(newVal) < 0){ currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = ([existingVal,newVal]).join(',');
}
} else {
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = newVal;
}
} else {
/** Numeric*/
if(summaryField.operation == 'COUNT'){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = 0.0; }
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = childrenArry.length;
} else if(summaryField.operation == 'MAX'){
if(current[summaryField.dataField] != null){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = current[summaryField.dataField];
} currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] =
Math.max(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField],current[summaryField.dataField]);
} } else if(summaryField.operation == 'MIN'){
if(current[summaryField.dataField] != null){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = current[summaryField.dataField];
} currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] =
Math.min(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField],current[summaryField.dataField]);
} } else if(summaryField.operation == 'SUM'){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = 0.0; }
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] += Number(current[summaryField.dataField]);
} else if(summaryField.operation == 'AVG'){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = 0.0; }
if(current[summaryField.dataField] != null){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField+'KOUNT'] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField+'KOUNT'] = 0;
}
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField+'KOUNT'] +=1;
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] += Number(current[summaryField.dataField]);
} } else if(summaryField.summaryFunction != null){
if(currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] == null){
currentGroups[depth]['summaryObjArry'][i][summaryField.dataField] = 0.0; }
}
} }
for each(var sf:SummaryField in SummaryRow(summaries[i]).fields) {
if(sf.summaryFunction != null){
currentGroups[depth]['summaryObjArry'][i][sf.dataField]
= expandExponents(sf.summaryFunction(currentGroups[depth]['summaryObjArry'][i],
depth,current,sf.dataField,sf.operation));
} }
insertSummary(currentGroups[depth],currentGroups[depth]['summaryObjArry'], summaries);
}
}
/**
* Grand Totals
*/
private function calculateRootSummariesLOOP(current:Object):void {
for (var i:int = 0; i < summaries.length; i++) {
for each(var summaryField:SummaryField in SummaryRow(summaries[i]).fields) {
if(summaryField.operation == 'STRINGAGG'){
/** Alphanumeric */
} else {
/** Numeric*/
if(_generatedRootSummaries[i][summaryField.dataField] == null){
_generatedRootSummaries[i][summaryField.dataField] = 0.0; }
if(summaryField.operation == 'COUNT'){
_generatedRootSummaries[i][summaryField.dataField] = 0;
} else if(summaryField.operation == 'MAX'){
_generatedRootSummaries[i][summaryField.dataField] =
Math.max(_generatedRootSummaries[i][summaryField.dataField],current[summaryField.dataField]);
} else if(summaryField.operation == 'MIN'){
_generatedRootSummaries[i][summaryField.dataField] =
Math.min(_generatedRootSummaries[i][summaryField.dataField],current[summaryField.dataField]);
} else if(summaryField.operation == 'SUM'){
_generatedRootSummaries[i][summaryField.dataField] += Number(current[summaryField.dataField]);
} else if(summaryField.operation == 'AVG'){
if(current[summaryField.dataField] != null){
if(_generatedRootSummaries[i][summaryField.dataField+'KOUNT'] == null){
_generatedRootSummaries[i][summaryField.dataField+'KOUNT'] = 0;
}
_generatedRootSummaries[i][summaryField.dataField+'KOUNT'] +=1;
_generatedRootSummaries[i][summaryField.dataField] += Number(current[summaryField.dataField]);
}
} else if(summaryField.summaryFunction != null){
}
}
} for each(var sf:SummaryField in SummaryRow(summaries[i]).fields) {
if(sf.summaryFunction != null){
_generatedRootSummaries[i][sf.dataField]
= expandExponents(sf.summaryFunction(_generatedRootSummaries[i],
-1,current,sf.dataField,sf.operation));
} } } }
private function calculateRootSummariesEND():void {
for (var i:int = 0; i < summaries.length; i++) {
for each(var summaryField:SummaryField in SummaryRow(summaries[i]).fields) {
if(summaryField.operation == 'COUNT'){
_generatedRootSummaries[i][summaryField.dataField] = (source as ICollectionView).length;
} else if(summaryField.operation == 'AVG'){
_generatedRootSummaries[i][summaryField.dataField] /= _generatedRootSummaries[i][summaryField.dataField+'KOUNT'];
}
} } }
public function get generatedRootSummaries():Array {
return _generatedRootSummaries==null?[new SummaryObject]:_generatedRootSummaries;
}
private var _generatedRootSummaries:Array;
/**********https://bugs.adobe.com/jira/browse/SDK-22643***********/
public function expandExponents(value:String):String {
if(value && value.toLowerCase().indexOf("e") > -1) { var regExp:RegExp = /^([+-])?(\d+).?(\d*)[eE]([-+]?\d+)$/;
var result:Array = regExp.exec(value);
var sign:String = result[1];
var first:String = result[2];
var last:String = result[3];
var exp:int = int(result[4]);
if (!exp){
return (sign ? sign : "") + (first ? first : "0") + (last ? "." + last : "");
}
var r:String = first + last;
var decimal:Boolean = exp < 0;
if (decimal){
var o:Number = -1 * (first.length + exp) + 1;
return (sign ? sign : "") + "0." + new Array(o).join("0") + r;
} else {
var i:Number = exp + first.length;
if (i >= r.length)
return (sign ? sign : "") + r + new Array(i - r.length + 1).join("0");
else
return (sign ? sign : "") + r.substr(0,i) + "." + r.substr(i);
}
} return value;
}
}
}