/* * @author Galaburda Oleg a_[w] * http://actualwave.com/ * */ package aw.external{ import aw.errors.SingletonError; import aw.utils.object_utils; import flash.external.ExternalInterface; import flash.utils.Proxy; import flash.utils.flash_proxy; /** EICallback класс, который, регистрирует, запрещает перезапись и управляет калбеками ExternalInterface. К калбекам можно получить досуп или задать калбек, как простое свойство объекта. Имя свойства будет передано, как имя метода калбека видимого извне. Доступен перебор с помошью for...in и for each...in. Удалять калбеки с помощью delete object[name]. */ dynamic public class EICallback extends Proxy{ static public const ONLY_FUNCTIONS_ERROR:String = 'EICallback Error: Only functions was acceptable.'; static public const ALREADY_EXISTS_ERROR:String = 'EICallback Error: Callback function already exists.'; static public const instance:EICallback = new EICallback(); protected var _removedCallHandler:Function; protected var _callbacks:Object = new Object(); protected var _names:Array = new Array(); public function EICallback():void{ super(); if(instance) throw new SingletonError(SingletonError.ERROR); } /** * Задаёт метод который будет подставлен вместо удалённых каллбеков, во избежание ошибок. * Калбек удалить нельзя, после удаления калбека, всё равно, остаёться закреплённая за ним * JavaScript-функция, которая будет вызвана при обращении к удалённому калбеку. Но возврашать * будет значение "undefined". А в такой способ вы можете задать метод, который будет * возвращать определённое значение. */ object_utils function set removedCallHandler(f:Function):void{ this._removedCallHandler = f; } object_utils function get removedCallHandler():Function{ return this._removedCallHandler; } override flash_proxy function callProperty(name:*, ...args:Array):*{ return this._callbacks[name].apply(this, args); } override flash_proxy function hasProperty(name:*):Boolean{ return name in this._callbacks; } override flash_proxy function deleteProperty(name:*):Boolean{ ExternalInterface.addCallback(name, _removedCallHandler); var ret:Boolean = delete this._callbacks[name]; if(ret){ var i:int = this._names.indexOf(String(name)); if(i>=0) this._names.splice(i, 1); } return ret; } override flash_proxy function getProperty(name:*):*{ return this._callbacks[name]; } override flash_proxy function setProperty(name:*, value:*):void{ if(value is Function){ if(name in this._callbacks) throw new Error(ALREADY_EXISTS_ERROR); else{ this._callbacks[name] = value; this._names.unshift(String(name)); ExternalInterface.addCallback(name, value); } }else if(value==null){ ExternalInterface.addCallback(name, _removedCallHandler); this._callbacks[name] = value; var i:int = this._names.indexOf(String(name)); if(i>=0) this._names.splice(i, 1); }else throw new Error(ONLY_FUNCTIONS_ERROR); } override flash_proxy function nextNameIndex(i:int):int{ if (i