Search code examples
javascriptactionscriptdhtml

Replace JavaScript with ActionScript in DHTML


I need to write a DHTML page. But, since I have most of the code inside an AS3 library, I want to use ActionScript instead of JavaScript to do the most of work. In this case JavaScript layer (if any) would be just a write-once abstract proxy.

I know about ExternalInterface stuff, but I want something more high-level, which would ease creation of the JS proxy layer.

Any advice?


Solution

  • I did an event driven gateway interface between ActionScript and JavaScript before:

    IGateway.as

    package gateway {
        import GatewayEvent;
    
        public interface IGateway {
            function send(event:GatewayEvent):void;
            function receive(event:GatewayEvent):void;
        }
    }
    

    GatewayEvent.as

    package gateway
    {
        import flash.events.Event;
    
        public class GatewayEvent extends Event {
            public var message:Object;
            public var flashId:String;
    
            public static const APP_START:String = 'appStart';
            public static const APP_END:String = 'appEnd';
            public static const APP_READY:String = 'appReady';
    
            public function GatewayEvent(flashId:String, type:String, message:Object = null) {
                super(type, false, false);
                this.flashId = flashId;
                this.message = message;
            }
        }
    }
    

    Gateway.as

    package gateway {
        import flash.external.ExternalInterface;
        import flash.events.EventDispatcher;
    
        import GatewayEvent;
        import IGateway;
    
        public class Gateway extends EventDispatcher implements IGateway {
            private static const _instance:Gateway = new Gateway(SingletonLock);
    
            public function Gateway(lock:Class) {
                if (lock != SingletonLock) {
                    throw new Error("invalid Singleton access.")
                }
                if (ExternalInterface.available) {
                    ExternalInterface.addCallback('relayEvent', relayEvent);
                }
            }
    
            public static function get instance():Gateway {
                return _instance;
            }
    
            public function send(event:GatewayEvent):void{
                if (ExternalInterface.available) {
                        ExternalInterface.call("$.gateway.receive", event.flashId, event.type, event.message);
                }
            }
    
            public function receive(event:GatewayEvent):void{
                dispatchEvent(event);
            }
    
            protected function relayEvent(flashId:String, type:String, message:Object):void {
                Gateway.instance.receive(new GatewayEvent(flashId, type, message));
            }
        }
    }
    
    class SingletonLock {}
    

    messenger.js (require jquery)

    (function($){
      /*
      *  Messenger
      *  A basic facility for global message passing (event passing)
      */
    
      // constructor
      $.Messenger = function(){
        this.events = {};
      };
    
      // member functions
      $.Messenger.prototype = {
        /*
        * @name  send
        * @param String subject   subject of this message. (Event name)
        * @param Object message   body of the message containing relavent data in key value pairs.
        * @param Mixed  sender    the object responsible for sending this message.
        *
        * @desc  Sends a message out to all message listeners
        */
        send : function(subject, message, sender){
          var handlers = this.events[subject];
          if (!handlers) { return; }
          for (var i = 0; i < handlers.length; i++) {
            handlers[i].fn.call(handlers[i].scope, sender, message);
          }
        },
    
        /*
        * @name  on
        * @param String   subject   subject (Event name) to listen to
        * @param Function fn        Message Handler of signature function(sender, message)
        * @param Object   scope     the scope in which the handler will run
        *
        * @desc  Subscribe / listen to a mesasge
        */
        on : function(subject, fn, scope){
          this.events[subject] = this.events[subject] || [];
          var handler = {};
          handler.fn = fn;
          handler.scope = scope;
          this.events[subject].push(handler);
        },
    
        /*
        * @name  un
        * @param String   subject   subject (Event name) to stop listen to
        * @param Function fn        Message Handler of signature function(sender, message)
        * @param Object   scope     the scope in which the handler was run
        *
        * @desc  Unsubscribe / stop listening to a message
        */
        un : function(subject, fn, scope){
          var handlers = this.events[subject];
          if (!handlers) { return; }
          scope = scope;
          for (var i = 0; i < handlers.length; i++) {
            if (handlers[i].fn === fn && handlers[i].scope === scope) {
              handlers.splice(i--, 1);
            }
          }
        }
      };
    
      // singloten glboal messenger
      $.messenger = new $.Messenger();
    
      // shortcut for jquery elements to subscribe to a message event
      $.fn.listen = function(subject, fn){
        $.messenger.on(subject, fn, this);
      };
    
      // shortcut for jquery elements to unsubscribe to a message event
      $.fn.reject = function(subject, fn){
        $.messenger.un(subject, fn, this);
      };
    
      // shortcut for jquery elements to broadcast/fire a message event
      $.fn.broadcast = function(subject, message) {
        $.messenger.send(subject, message, this);
      };
    
    })(jQuery);
    

    gateway.js (require jquery)

    (function($) {
      $.gateway = {
    
        messenger : new $.Messenger(),
    
        send: function(flashId, eventName, message){
          var sender = $('#'+flashId)[0];
          sender.relayEvent(flashId, eventName, message);
        },
    
        receive: function(flashId, eventName, message){
          var sender = $('#'+flashId)[0];
          $.gateway.messenger.send(eventName, message, sender);
        },
    
        listen: function(flashId, eventName, fn) {
          $.gateway.messenger.on(eventName, fn, $('.' + flashId)[0]);
        }
      };
    })(jQuery);