package { import flash.display.DisplayObject; import flash.display.Loader; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.MouseEvent; import flash.events.SecurityErrorEvent; import flash.external.ExternalInterface; import flash.net.URLLoader; import flash.net.URLRequest; import flash.system.Security; import flash.utils.setTimeout; public class ServiceAPIExample extends Sprite { public const METADATA_ENDPOINT:String = "http://cache.addthiscdn.com/services/v1/sharing.en.xml"; public const MAX_REQUESTS:uint = 4; public const DEFAULT_ICON_SIZE:uint = 16; public const PADDING:uint = 8; private var xmlLoader:URLLoader; private var metadata:XML; private var iconSize:uint = DEFAULT_ICON_SIZE; private var positions:Array; private var services:Array; private var icon_queue:Array; private var active_requests:uint = 0; public function ServiceAPIExample() { trace('ServiceAPIExample!'); super(); Security.allowDomain(METADATA_ENDPOINT); if (!stage) addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); else onAddedToStage(); } private function onAddedToStage(evt:*=null):void { trace('Added to stage!'); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.RESIZE, onResize); if (!xmlLoader) loadServiceMetadata(); } private function onResize(evt:*=null):void { if (services) rebuildPositions(); } private function loadServiceMetadata():void { trace('Loading service metadata...'); xmlLoader = new URLLoader(); xmlLoader.addEventListener(Event.COMPLETE, onXMLLoaded); xmlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError); xmlLoader.load(new URLRequest( METADATA_ENDPOINT )); } private function onXMLLoaded( evt:Event ):void { trace('XML loaded!'); // Parse string into XML metadata = XML(xmlLoader.data); // Loop over all services, loading their thumbs services = []; for each (var service:XML in metadata..service) { var s:ServiceMetadata = new ServiceMetadata( service.code.toString(), service.name.toString(), service.icon.toString() ); services.push(s); addChild(s.loader); } rebuildPositions(); icon_queue = services.slice(0); dequeue(); } private function rebuildPositions():void { positions = []; var stage_width:uint = stage.stageWidth, x:uint = PADDING, y:uint = 0; for (var i:uint=0, L:uint=services.length; i < L; i++) { positions.push({ x:x, y:y }); positionThumb(services[i]); x += PADDING + iconSize; if ( x + iconSize >= stage_width ){ x = PADDING; y += PADDING + iconSize; } } } private function positionThumb(service:ServiceMetadata):void { var thumb:Loader = service.loader, p:Object = positions[service.idx]; thumb.x = p.x; thumb.y = p.y; thumb.width = thumb.height = iconSize; } private function dequeue():void { if ( icon_queue.length <= 0 ) return; if ( active_requests >= MAX_REQUESTS ) return; // wait for more icons to finish loadThumb(icon_queue.shift()); setTimeout(dequeue, 50); } private function loadThumb(service:ServiceMetadata):void { var loader:Loader = service.loader; loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:*=null):void { trace(' --> Icon '+service.code+' Loaded!'); active_requests--; positionThumb(service); loader.addEventListener(MouseEvent.ROLL_OVER, function(evt:*=null):void { ExternalInterface.call('displayMetadata', service.name, service.code); }); dequeue(); }); trace('Loading Icon for '+service.code+' from '+service.icon+' [active='+active_requests+', queue='+icon_queue.length+']'); active_requests++; loader.load(new URLRequest(service.icon)); } private function onError( evt:* ):void { active_requests--; trace('ONOES! '+evt); } } } import flash.display.Loader; class ServiceMetadata { private static var _currentIndex:uint = 0; public var idx:uint; public var code:String; public var name:String; public var icon:String; public var loader:Loader; function ServiceMetadata(code:String, name:String, icon:String){ this.idx = _currentIndex++; this.code = code; this.name = name; this.icon = icon; loader = new Loader(); } }