package com.shawnblais.utils { import flash.utils.Proxy; import flash.utils.flash_proxy; use namespace flash_proxy; public class IndexedObject extends Proxy { /** Maintains a count of all objects **/ protected var count:uint; /** Main object **/ protected var object:Object; /** List to hold reference to all property names. Allows us to easily get length, and also access object properties using a numerical index. **/ protected var propertyList:Vector.; public function get length():uint { return count; } public function IndexedObject(useList:Boolean = true) { super(); // useList enables allows you to access the object using an index (getItemAt, setItemAt, etc). // But comes with a performance cost. if(useList){ propertyList = new Vector.; } object = {}; count = 0; } public function getItemAt(index:uint):* { if(!propertyList){ throwListError(); return; } return object[propertyList[index]]; } public function setItemAt(index:uint, value:*):void { if(!propertyList){ throwListError(); return; } this[propertyList[index]] = value; } //Normally this would return the value removed which was removed. But in our case, we null out the value...so what's the point? public function removeItemAt(index:uint):void { if(!propertyList){ throwListError(); return; } this[propertyList[index]] = null } public function removeAll():void { if(propertyList){ propertyList = new Vector.; } count = 0; object = {}; } flash_proxy override function getProperty(name:*):*{ return object[name]; } flash_proxy override function setProperty(name:*, value:*):void { if(value == null){ //Remove object from property list if it previously existed. if(object[name] != null){ if(propertyList){ var l:uint = length; //indexOf uses strict equality, which doesn't seem to work here. Loop manually. for(var i:uint = 0; i < l; i++){ if(propertyList[i] == name){ break; }} propertyList.splice(i, 1); } count--; object[name] = null; } } else{ //Add object to propertyList if doesn't already exist if(object[name] == null){ if(propertyList){ propertyList[count] = name; } count++; } object[name] = value; } } protected function throwListError():void { throw new Error("Can not access this IndexedObject using a numerical index. Pass 'true' to the constructor to enable this feature. "); } /** * Functions to support for..in, and for..each loops **/ override flash_proxy function nextNameIndex(index:int):int { if (index > propertyList.length-1) return 0; return index + 1; } override flash_proxy function nextName(index:int):String { return propertyList[index-1]; } override flash_proxy function nextValue(index:int):* { return object[propertyList[index-1]]; } } }