package com.joangarnet.js { import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.external.ExternalInterface; import flash.utils.Proxy; import flash.utils.flash_proxy; import flash.utils.ByteArray; import org.phprpc.util.Base64; /* * Original class: Joan Garnet http://www.joangarnet.com/blog/?p=437 * Patched by Pedro Casaubon * This patch add Base64 encoding/decoding to the Injected Code */ dynamic final public class JavaScript extends Proxy implements IEventDispatcher { private var eventDispatcher:EventDispatcher; /* * scope for calling the Javascript methods and properties. Defaults to DOM's window object. */ public static const WINDOW:String = ""; public static const DOCUMENT:String = "document"; private var scope:String; /* * javascript toolkit to do some internal tasks */ private const JSProxyTools:XML = ; /* * end javascript toolkit */ private var movieID:String; public function JavaScript(movieID:String,url:String=null) { this.movieID = movieID; if( !ExternalInterface.available ){ throw new Error("ExternalInterface not available"); } eventDispatcher = new EventDispatcher(this); ExternalInterface.marshallExceptions = true; // compile internal toolkit try{ ExternalInterface.call( "eval", JSProxyTools.toString() ); }catch(err:Error){ throw new Error( "com.joangarnet.js.JavaScript::constructor()\ngetStackTrace() "+ err.getStackTrace() ); } // handle the loaded script callback ExternalInterface.addCallback( "jsLoadedHandler", jsLoaded ); if(url)this.url = url; } private function callToolkit( methodName:String, params_arr:Array ):* { var res:*; try{ res = ExternalInterface.call( "com.joangarnet.JSProxy.facade", movieID, methodName, params_arr ); }catch(err:Error){ throw new Error( "com.joangarnet.js.JavaScript::callToolkit()\ngetStackTrace() "+ err.getStackTrace() ); } return res; } private function set url( url:String ):void { callToolkit( "loadScript", [url] ); } public function set js( jsCode:String ):void { compile( jsCode ); } public function getScope( scope:String=WINDOW ):JavaScript { this.scope = scope.replace( /^(window\.?)(.*)/i, "$2" ); return this; } private function jsLoaded():void { trace("jsLoaded!"); dispatchEvent( new Event(Event.COMPLETE) ); } /* * Modified method to support Base64 encoding * @author Pedro Casaubon (http://www.xperiments.es/blog) */ private function compile( jsCode:String ):void { // javascript compilation try{ var ba:ByteArray = new ByteArray(); ba.writeUTFBytes( jsCode ); ba.position = 0; var baseCode:String = Base64.encode( ba ); callToolkit( "compileCode", [baseCode] ); }catch(err:Error){ throw new Error( "com.joangarnet.js.JavaScript::compile() javascript compilation error\ngetStackTrace() "+ err.getStackTrace() ); } dispatchEvent( new Event(Event.COMPLETE) ); } private function buildPath( objectMember:String ):String { return (scope.length>0 ? scope+"."+objectMember : objectMember); } /* * Proxy implementation */ override flash_proxy function callProperty(methodName:*, ... args):* { var res:*; var functionCall:String = buildPath((methodName as QName).localName); try{ args = args!=null ? args : []; args.unshift( functionCall ); res = ExternalInterface.call.apply(null, args); }catch(err:Error){ throw new Error( "com.joangarnet.js.JavaScript::"+functionCall+"()\ngetStackTrace() "+ err.getStackTrace() ); } return res; } override flash_proxy function getProperty(name:*):* { return callToolkit( "getProperty", [buildPath((name as QName).localName)] ); } override flash_proxy function setProperty(name:*, value:*):void { callToolkit( "setProperty", [buildPath((name as QName).localName), value] ); } /* * IEventDispatcher implementation */ public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference); } public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { eventDispatcher.removeEventListener(type, listener, useCapture); } public function dispatchEvent(event:Event):Boolean { return eventDispatcher.dispatchEvent(event); } public function hasEventListener(type:String):Boolean { return eventDispatcher.hasEventListener(type); } public function willTrigger(type:String):Boolean { return eventDispatcher.willTrigger(type); } } }