Project

General

Profile

Statistics
| Revision:

root / trunk / web / dojo / dojox / flash / DojoExternalInterface.as

History | View | Annotate | Download (5.31 KB)

1
/**
2
	A wrapper around Flash 8's ExternalInterface; this is needed
3
	because ExternalInterface has a number of serialization bugs that we 
4
	need to correct for.
5
	
6
	@author Brad Neuberg
7
*/
8

    
9
import flash.external.ExternalInterface;
10

    
11
class DojoExternalInterface{
12
	public static var available:Boolean;
13
	public static var dojoPath = "";
14
		
15
	public static function initialize(){
16
		//trace("DojoExternalInterface.initialize");
17
		
18
		// extract the dojo base path
19
		DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
20
		
21
		// see if we need to do an express install
22
		var install:ExpressInstall = new ExpressInstall();
23
		if(install.needsUpdate){
24
			install.init();
25
		}
26
		
27
		// set whether communication is available
28
		DojoExternalInterface.available = ExternalInterface.available;
29
		
30
		// make sure we can play nice in XD settings
31
		System.security.allowDomain(unescape(_root.xdomain));
32
	}
33
	
34
	/** Called when we are finished adding methods through addCallback. */
35
	public static function done(){
36
		//trace("done");
37
		DojoExternalInterface.call("dojox.flash.loaded");
38
	}
39
	
40
	public static function addCallback(methodName:String, instance:Object, 
41
									   method:Function):Boolean{
42
		//trace("addCallback");
43
		ExternalInterface.addCallback(methodName, instance, function(){
44
			instance = (instance) ? instance : null;
45
			var params = [];
46
			if(arguments && arguments.length){
47
				for(var i = 0; i < arguments.length; i++){
48
					params[i] = DojoExternalInterface.decodeData(arguments[i]);
49
				}
50
			}
51
			
52
			var results = method.apply(instance, params);
53
			results = DojoExternalInterface.encodeData(results);
54
			
55
			return results;
56
		});
57
		
58
		// tell JavaScript about DojoExternalInterface new method so we can create a proxy
59
		ExternalInterface.call("dojox.flash.comm._addExternalInterfaceCallback", 
60
													 methodName);
61
													 
62
		return true;
63
	}
64
	
65
	public static function call(methodName:String):Void{
66
		// we might have any number of optional arguments, so we have to 
67
		// pass them in dynamically; strip out the results callback
68
		var parameters = new Array();
69
		for(var i = 0; i < arguments.length; i++){
70
			parameters.push(arguments[i]);
71
		}
72
		
73
		// FIXME: Should we be encoding or decoding the data to get
74
		// around Flash's serialization bugs?
75
		
76
		var results = ExternalInterface.call.apply(ExternalInterface, parameters);
77
		
78
		return results;
79
	}
80
	
81
	/** 
82
		Called by Flash to indicate to JavaScript that we are ready to have
83
		our Flash functions called. Calling loaded()
84
		will fire the dojox.flash.loaded() event, so that JavaScript can know that
85
		Flash has finished loading and adding its callbacks, and can begin to
86
		interact with the Flash file.
87
	*/
88
	public static function loaded(){
89
		DojoExternalInterface.call("dojox.flash.loaded");
90
	}
91
	
92
	/**
93
		Utility trace implementation that prints out to console.debug.
94
	*/
95
	public static function trace(msg){
96
		DojoExternalInterface.call("console.debug", "FLASH: " + msg);
97
	}
98
	
99
	private static function decodeData(data):String{
100
		if(!data || typeof data != "string"){
101
			return data;
102
		}
103
		
104
		//      JAC: Using unicode character 0001 to store instead of Unicode null 
105
		//      which causes trouble 
106
		data = replaceStr(data, "&custom_null;", "\u0001");
107
		
108
		// we have to use custom encodings for certain characters when passing
109
		// them over; for example, passing a backslash over as //// from JavaScript
110
		// to Flash doesn't work
111
		data = replaceStr(data, "&custom_backslash;", "\\");
112
		
113
		return data;
114
	}
115
	
116
	private static function encodeData(data):String{	
117
		if(!data || typeof data != "string"){
118
			return data;
119
		}
120
		
121
		// double encode all entity values, or they will be mis-decoded 
122
		// by Flash when returned 
123
		data = replaceStr(data, "&", "&amp;");
124
		
125
		// certain XMLish characters break Flash's wire serialization for
126
		// ExternalInterface; encode these into a custom encoding, rather than
127
		// the standard entity encoding, because otherwise we won't be able to
128
		// differentiate between our own encoding and any entity characters
129
		// that are being used in the string itself
130
		data = replaceStr(data, '<', '&custom_lt;');
131
		data = replaceStr(data, '>', '&custom_gt;');
132
		
133
		// needed for IE
134
		data = replaceStr(data, '\\', '&custom_backslash;');
135
		data = replaceStr(data, "\u0001", "&custom_null;");
136
		
137
		// encode control characters and JavaScript delimiters
138
		data = replaceStr(data, "\n", "\\n");
139
		data = replaceStr(data, "\r", "\\r");
140
		data = replaceStr(data, "\f", "\\f");
141
		data = replaceStr(data, "'", "\\'");
142
		data = replaceStr(data, '"', '\"');
143
		
144
		return data;
145
	}
146
	
147
	/** 
148
			Flash ActionScript has no String.replace method or support for
149
			Regular Expressions! We roll our own very simple one.
150
	*/
151
	public static function replaceStr(inputStr:String, replaceThis:String, 
152
										withThis:String):String{
153
		var splitStr = inputStr.split(replaceThis);
154
		if(!splitStr){
155
			return inputStr;
156
		}
157
		
158
		inputStr = splitStr.join(withThis);
159
		return inputStr;
160
	}
161
	
162
	private static function getDojoPath(){
163
		var url = _root._url;
164
		var start = url.indexOf("baseUrl=") + "baseUrl=".length;
165
		var path = url.substring(start);
166
		var end = path.indexOf("&");
167
		if(end != -1){
168
			path = path.substring(0, end);
169
		}
170
		
171
		// some browsers append a junk string at the end: '%20'%20quality=
172
		if(path.indexOf("'%20'%20quality=") != -1){
173
			path = path.substring(0, path.indexOf("'%20'%20quality="));
174
		}
175
		return unescape(path);
176
	}
177
}