// Copyright 2007. Adobe Systems Incorporated. All Rights Reserved. package fl.data { import flash.events.EventDispatcher; import fl.events.DataChangeEvent; import fl.events.DataChangeType; import RangeError; //-------------------------------------- // Events //-------------------------------------- /** * Dispatched before the data is changed. * * @see #event:dataChange dataChange event * * @eventType fl.events.DataChangeEvent.PRE_DATA_CHANGE * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="preDataChange", type="fl.events.DataChangeEvent")] /** * Dispatched after the data is changed. * * @see #event:preDataChange preDataChange event * * @eventType fl.events.DataChangeEvent.DATA_CHANGE * * @langversion 3.0 * @playerversion Flash 9.0.28.0 */ [Event(name="dataChange", type="fl.events.DataChangeEvent")] //-------------------------------------- // Class description //-------------------------------------- /** * The student_ar_fl_data_DataProvider class provides methods and properties that allow you to query and modify * the data in any list-based component--for example, in a List, DataGrid, TileList, or ComboBox * component. * *
A data provider is a linear collection of items that serve as a data source--for
* example, an array. Each item in a data provider is an object or XML object that contains one or
* more fields of data. You can access the items that are contained in a data provider by index, by
* using the student_ar_fl_data_DataProvider.getItemAt()
method.
DataChangeEvent.INVALIDATE_ALL
event. Items are invalidated after they
* are changed; the student_ar_fl_data_DataProvider automatically redraws the invalidated items.
*
* @see #invalidateItem()
* @see #invalidateItemAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function invalidate():void {
dispatchEvent(new DataChangeEvent(DataChangeEvent.DATA_CHANGE, DataChangeType.INVALIDATE_ALL,data.concat(),0,data.length));
}
/**
* Adds a new item to the data provider at the specified index.
* If the index that is specified exceeds the length of the data provider,
* the index is ignored.
*
* @param item An object that contains the data for the item to be added.
*
* @param index The index at which the item is to be added.
*
* @throws RangeError The specified index is less than 0 or greater than or equal
* to the length of the data provider.
*
* @see #addItem()
* @see #addItems()
* @see #addItemsAt()
* @see #getItemAt()
* @see #removeItemAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function addItemAt(item:Object,index:uint):void {
checkIndex(index,data.length);
dispatchPreChangeEvent(DataChangeType.ADD,[item],index,index);
data.splice(index,0,item);
dispatchChangeEvent(DataChangeType.ADD,[item],index,index);
}
/**
* Appends an item to the end of the data provider.
*
* @param item The item to be appended to the end of the current data provider.
*
* @includeExample examples/student_ar_fl_data_DataProvider.constructor.1.as -noswf
*
* @see #addItemAt()
* @see #addItems()
* @see #addItemsAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function addItem(item:Object):void {
dispatchPreChangeEvent(DataChangeType.ADD,[item],data.length-1,data.length-1);
data.push(item);
dispatchChangeEvent(DataChangeType.ADD,[item],data.length-1,data.length-1);
}
/**
* Adds several items to the data provider at the specified index and dispatches
* a DataChangeType.ADD
event.
*
* @param items The items to be added to the data provider.
*
* @param index The index at which the items are to be inserted.
*
* @throws RangeError The specified index is less than 0 or greater than or equal
* to the length of the data provider.
*
* @see #addItem()
* @see #addItemAt()
* @see #addItems()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function addItemsAt(items:Object,index:uint):void {
checkIndex(index,data.length);
var arr:Array = getDataFromObject(items);
dispatchPreChangeEvent(DataChangeType.ADD,arr,index,index+arr.length-1);
data.splice.apply(data, [index,0].concat(arr));
dispatchChangeEvent(DataChangeType.ADD,arr,index,index+arr.length-1);
}
/**
* Appends multiple items to the end of the student_ar_fl_data_DataProvider and dispatches
* a DataChangeType.ADD
event. The items are added in the order
* in which they are specified.
*
* @param items The items to be appended to the data provider.
*
* @includeExample examples/student_ar_fl_data_DataProvider.addItems.1.as -noswf
*
* @see #addItem()
* @see #addItemAt()
* @see #addItemsAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function addItems(items:Object):void {
addItemsAt(items,data.length);
}
/**
* Concatenates the specified items to the end of the current data provider.
* This method dispatches a DataChangeType.ADD
event.
*
* @param items The items to be added to the data provider.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*
* @see #addItems()
* @see #merge()
*
* @internal Is this method any different than addItems()? It's not clear.
* I also thing "concatenates the items *to*" sounds odd. Perhaps
* the concatenated items are added to the end of the data provider?
*/
public function concat(items:Object):void {
addItems(items);
}
/**
* Appends the specified data into the data that the data provider
* contains and removes any duplicate items. This method dispatches
* a DataChangeType.ADD
event.
*
* @param data Data to be merged into the data provider.
*
* @see #concat()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function merge(newData:Object):void {
var arr:Array = getDataFromObject(newData);
var l:uint = arr.length;
var startLength:uint = data.length;
dispatchPreChangeEvent(DataChangeType.ADD,data.slice(startLength,data.length),startLength,this.data.length-1);
for (var i:uint=0; iDataChangeType.REMOVE
* event.
*
* @param index Index of the item to be removed.
*
* @return The item that was removed.
*
* @throws RangeError The specified index is less than 0 or greater than
* or equal to the length of the data provider.
*
* @see #removeAll()
* @see #removeItem()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function removeItemAt(index:uint):Object {
checkIndex(index,data.length-1);
dispatchPreChangeEvent(DataChangeType.REMOVE, data.slice(index,index+1), index, index);
var arr:Array = data.splice(index,1);
dispatchChangeEvent(DataChangeType.REMOVE,arr,index,index);
return arr[0];
}
/**
* Removes the specified item from the data provider and dispatches a DataChangeType.REMOVE
* event.
*
* @param item Item to be removed.
*
* @return The item that was removed.
*
* @see #removeAll()
* @see #removeItemAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function removeItem(item:Object):Object {
var index:int = getItemIndex(item);
if (index != -1) {
return removeItemAt(index);
}
return null;
}
/**
* Removes all items from the data provider and dispatches a DataChangeType.REMOVE_ALL
* event.
*
* @see #removeItem()
* @see #removeItemAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function removeAll():void {
var arr:Array = data.concat();
dispatchPreChangeEvent(DataChangeType.REMOVE_ALL,arr,0,arr.length);
data = [];
dispatchChangeEvent(DataChangeType.REMOVE_ALL,arr,0,arr.length);
}
/**
* Replaces an existing item with a new item and dispatches a DataChangeType.REPLACE
* event.
*
* @param oldItem The item to be replaced.
*
* @param newItem The replacement item.
*
* @return The item that was replaced.
*
* @throws RangeError The item could not be found in the data provider.
*
* @see #replaceItemAt()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function replaceItem(newItem:Object,oldItem:Object):Object {
var index:int = getItemIndex(oldItem);
if (index != -1) {
return replaceItemAt(newItem,index);
}
return null;
}
/**
* Replaces the item at the specified index and dispatches a DataChangeType.REPLACE
* event.
*
* @param newItem The replacement item.
*
* @param index The index of the item to be replaced.
*
* @return The item that was replaced.
*
* @throws RangeError The specified index is less than 0 or greater than
* or equal to the length of the data provider.
*
* @see #replaceItem()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function replaceItemAt(newItem:Object,index:uint):Object {
checkIndex(index,data.length-1);
var arr:Array = [data[index]];
dispatchPreChangeEvent(DataChangeType.REPLACE,arr,index,index);
data[index] = newItem;
dispatchChangeEvent(DataChangeType.REPLACE,arr,index,index);
return arr[0];
}
/**
* Sorts the items that the data provider contains and dispatches a DataChangeType.SORT
* event.
*
* @param sortArg The arguments to use for sorting.
*
* @return The return value depends on whether the method receives any arguments.
* See the Array.sort()
method for more information.
* This method returns 0 when the sortOption
property
* is set to Array.UNIQUESORT
.
*
* @see #sortOn()
* @see Array#sort() Array.sort()
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function sort(...sortArgs:Array):* {
dispatchPreChangeEvent(DataChangeType.SORT,data.concat(),0,data.length-1);
var returnValue:Array = data.sort.apply(data,sortArgs);
dispatchChangeEvent(DataChangeType.SORT,data.concat(),0,data.length-1);
return returnValue;
}
/**
* Sorts the items that the data provider contains by the specified
* field and dispatches a DataChangeType.SORT
event.
* The specified field can be a string, or an array of string values that
* designate multiple fields to sort on in order of precedence.
*
* @param fieldName The item field by which to sort. This value can be a string
* or an array of string values.
*
* @param options Options for sorting.
*
* @return The return value depends on whether the method receives any arguments.
* For more information, see the Array.sortOn()
method.
* If the sortOption
property is set to Array.UNIQUESORT
,
* this method returns 0.
*
* @see #sort()
* @see Array#sortOn() Array.sortOn()
*
* @internal If an array of string values is passed, does the sort take place in
* the order that the string values are specified? Also, it might be helpful if "options
* for sorting" was more explicit. I wondered if that meant sort type, like merge sort
* or bubble sort, for example, but when I looked up "uniquesort" it seemed like not.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function sortOn(fieldName:Object,options:Object=null):* {
dispatchPreChangeEvent(DataChangeType.SORT,data.concat(),0,data.length-1);
var returnValue:Array = data.sortOn(fieldName,options);
dispatchChangeEvent(DataChangeType.SORT,data.concat(),0,data.length-1);
return returnValue;
}
/**
* Creates a copy of the current student_ar_fl_data_DataProvider object.
*
* @return A new instance of this student_ar_fl_data_DataProvider object.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function clone():student_ar_fl_data_DataProvider {
return new student_ar_fl_data_DataProvider(data);
}
/**
* Creates an Array object representation of the data that the data provider contains.
*
* @return An Array object representation of the data that the data provider contains.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
public function toArray():Array {
return data.concat();
}
/**
* Creates a string representation of the data that the data provider contains.
*
* @return A string representation of the data that the data provider contains.
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
override public function toString():String {
return "student_ar_fl_data_DataProvider ["+data.join(" , ")+"]";
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function getDataFromObject(obj:Object):Array {
var retArr:Array;
if (obj is Array) {
var arr:Array = obj as Array;
if (arr.length > 0) {
if (arr[0] is String || arr[0] is Number) {
retArr = [];
// convert to object array.
for (var i:uint = 0; i < arr.length; i++) {
var o:Object = {label:String(arr[i]),data:arr[i]}
retArr.push(o);
}
return retArr;
}
}
return obj.concat();
} else if (obj is student_ar_fl_data_DataProvider) {
return obj.toArray();
} else if (obj is XML) {
var xml:XML = obj as XML;
retArr = [];
var nodes:XMLList = xml.*;
for each (var node:XML in nodes) {
var obj:Object = {};
var attrs:XMLList = node.attributes();
for each (var attr:XML in attrs) {
obj[attr.localName()] = attr.toString();
}
var propNodes:XMLList = node.*;
for each (var propNode:XML in propNodes) {
if (propNode.hasSimpleContent()) {
obj[propNode.localName()] = propNode.toString();
}
}
retArr.push(obj);
}
return retArr;
} else {
throw new TypeError("Error: Type Coercion failed: cannot convert "+obj+" to Array or student_ar_fl_data_DataProvider.");
return null;
}
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function checkIndex(index:int,maximum:int):void {
if (index > maximum || index < 0) {
throw new RangeError("student_ar_fl_data_DataProvider index ("+index+") is not in acceptable range (0 - "+maximum+")");
}
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function dispatchChangeEvent(evtType:String,items:Array,startIndex:int,endIndex:int):void {
dispatchEvent(new DataChangeEvent(DataChangeEvent.DATA_CHANGE,evtType,items,startIndex,endIndex));
}
/**
* @private (protected)
*
* @langversion 3.0
* @playerversion Flash 9.0.28.0
*/
protected function dispatchPreChangeEvent(evtType:String, items:Array, startIndex:int, endIndex:int):void {
dispatchEvent(new DataChangeEvent(DataChangeEvent.PRE_DATA_CHANGE, evtType, items, startIndex, endIndex));
}
}
}