socky-client-rails 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/assets/socky.js ADDED
@@ -0,0 +1,1122 @@
1
+ /**
2
+ * Socky push-server JavaScript client
3
+ *
4
+ * @version 0.4.0
5
+ * @author Bernard Potocki <bernard.potocki@imanel.org>
6
+ * @license The MIT license.
7
+ * @source http://github.com/socky/socky-js
8
+ *
9
+ */
10
+
11
+ // Set URL of your WebSocketMain.swf here:
12
+ WEB_SOCKET_SWF_LOCATION = "/javascripts/socky/WebSocketMain.swf";
13
+ // Set this to dump debug message from Flash to console.log:
14
+ WEB_SOCKET_DEBUG = false;
15
+
16
+ Socky = function(host, port, params) {
17
+ this.host = host;
18
+ this.port = port;
19
+ this.params = params;
20
+ this.connect();
21
+ };
22
+
23
+ // Socky states
24
+ Socky.CONNECTING = 0;
25
+ Socky.AUTHENTICATING = 1;
26
+ Socky.OPEN = 2;
27
+ Socky.CLOSED = 3;
28
+ Socky.UNAUTHENTICATED = 4;
29
+
30
+ Socky.prototype.connect = function() {
31
+ var instance = this;
32
+ instance.state = Socky.CONNECTING;
33
+
34
+ var ws = new WebSocket(this.host + ':' + this.port + '/?' + this.params);
35
+ ws.onopen = function() { instance.onopen(); };
36
+ ws.onmessage = function(evt) { instance.onmessage(evt); };
37
+ ws.onclose = function() { instance.onclose(); };
38
+ ws.onerror = function() { instance.onerror(); };
39
+ };
40
+
41
+
42
+
43
+ // ***** Private methods *****
44
+ // Try to avoid any modification of these methods
45
+ // Modification of these methods may cause script to work invalid
46
+ // Please see 'public methods' below
47
+ // ***************************
48
+
49
+ // Called when connection is opened
50
+ Socky.prototype.onopen = function() {
51
+ this.state = Socky.AUTHENTICATING;
52
+ this.respond_to_connect();
53
+ };
54
+
55
+ // Called when socket message is received
56
+ Socky.prototype.onmessage = function(evt) {
57
+ try {
58
+ var request = JSON.parse(evt.data);
59
+ switch (request.type) {
60
+ case "message":
61
+ this.respond_to_message(request.body);
62
+ break;
63
+ case "authentication":
64
+ if(request.body == "success") {
65
+ this.state = Socky.OPEN;
66
+ this.respond_to_authentication_success();
67
+ } else {
68
+ this.state = Socky.UNAUTHENTICATED;
69
+ this.respond_to_authentication_failure();
70
+ }
71
+ break;
72
+ }
73
+ } catch (e) {
74
+ console.error(e.toString());
75
+ }
76
+ };
77
+
78
+ // Called when socket connection is closed
79
+ Socky.prototype.onclose = function() {
80
+ if(this.state != Socky.CLOSED && this.state != Socky.UNAUTHENTICATED) {
81
+ this.respond_to_disconnect();
82
+ }
83
+ };
84
+
85
+ // Called when error occurs
86
+ // Currently unused
87
+ Socky.prototype.onerror = function() {};
88
+
89
+
90
+
91
+ // ***** Public methods *****
92
+ // These methods can be freely modified.
93
+ // The change should not affect the normal operation of the script.
94
+ // **************************
95
+
96
+ // Called after connection but before authentication confirmation is received
97
+ // At this point user is still not allowed to receive messages
98
+ Socky.prototype.respond_to_connect = function() {
99
+ };
100
+
101
+ // Called when authentication confirmation is received.
102
+ // At this point user will be able to receive messages
103
+ Socky.prototype.respond_to_authentication_success = function() {
104
+ };
105
+
106
+ // Called when authentication is rejected by server
107
+ // This usually means that secret is invalid or that authentication server is unavailable
108
+ // This method will NOT be called if connection with Socky server will be broken - see respond_to_disconnect
109
+ Socky.prototype.respond_to_authentication_failure = function() {
110
+ };
111
+
112
+ // Called when new message is received
113
+ // Note that msg is not sanitized - it can be any script received.
114
+ Socky.prototype.respond_to_message = function(msg) {
115
+ eval(msg);
116
+ };
117
+
118
+ // Called when connection is broken between client and server
119
+ // This usually happens when user lost his connection or when Socky server is down.
120
+ // At default it will try to reconnect after 1 second.
121
+ Socky.prototype.respond_to_disconnect = function() {
122
+ var instance = this;
123
+ setTimeout(function() { instance.connect(); }, 1000);
124
+ }
125
+ /* SWFObject v2.2 <http://code.google.com/p/swfobject/>
126
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
127
+ */
128
+ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
129
+ /*
130
+ /*
131
+ Copyright 2006 Adobe Systems Incorporated
132
+
133
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
134
+ to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
135
+ and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
136
+
137
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
138
+
139
+
140
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
141
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
142
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
143
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
144
+
145
+ */
146
+
147
+
148
+ /*
149
+ * The Bridge class, responsible for navigating AS instances
150
+ */
151
+ function FABridge(target,bridgeName)
152
+ {
153
+ this.target = target;
154
+ this.remoteTypeCache = {};
155
+ this.remoteInstanceCache = {};
156
+ this.remoteFunctionCache = {};
157
+ this.localFunctionCache = {};
158
+ this.bridgeID = FABridge.nextBridgeID++;
159
+ this.name = bridgeName;
160
+ this.nextLocalFuncID = 0;
161
+ FABridge.instances[this.name] = this;
162
+ FABridge.idMap[this.bridgeID] = this;
163
+
164
+ return this;
165
+ }
166
+
167
+ // type codes for packed values
168
+ FABridge.TYPE_ASINSTANCE = 1;
169
+ FABridge.TYPE_ASFUNCTION = 2;
170
+
171
+ FABridge.TYPE_JSFUNCTION = 3;
172
+ FABridge.TYPE_ANONYMOUS = 4;
173
+
174
+ FABridge.initCallbacks = {};
175
+ FABridge.userTypes = {};
176
+
177
+ FABridge.addToUserTypes = function()
178
+ {
179
+ for (var i = 0; i < arguments.length; i++)
180
+ {
181
+ FABridge.userTypes[arguments[i]] = {
182
+ 'typeName': arguments[i],
183
+ 'enriched': false
184
+ };
185
+ }
186
+ }
187
+
188
+ FABridge.argsToArray = function(args)
189
+ {
190
+ var result = [];
191
+ for (var i = 0; i < args.length; i++)
192
+ {
193
+ result[i] = args[i];
194
+ }
195
+ return result;
196
+ }
197
+
198
+ function instanceFactory(objID)
199
+ {
200
+ this.fb_instance_id = objID;
201
+ return this;
202
+ }
203
+
204
+ function FABridge__invokeJSFunction(args)
205
+ {
206
+ var funcID = args[0];
207
+ var throughArgs = args.concat();//FABridge.argsToArray(arguments);
208
+ throughArgs.shift();
209
+
210
+ var bridge = FABridge.extractBridgeFromID(funcID);
211
+ return bridge.invokeLocalFunction(funcID, throughArgs);
212
+ }
213
+
214
+ FABridge.addInitializationCallback = function(bridgeName, callback)
215
+ {
216
+ var inst = FABridge.instances[bridgeName];
217
+ if (inst != undefined)
218
+ {
219
+ callback.call(inst);
220
+ return;
221
+ }
222
+
223
+ var callbackList = FABridge.initCallbacks[bridgeName];
224
+ if(callbackList == null)
225
+ {
226
+ FABridge.initCallbacks[bridgeName] = callbackList = [];
227
+ }
228
+
229
+ callbackList.push(callback);
230
+ }
231
+
232
+ // updated for changes to SWFObject2
233
+ function FABridge__bridgeInitialized(bridgeName) {
234
+ var objects = document.getElementsByTagName("object");
235
+ var ol = objects.length;
236
+ var activeObjects = [];
237
+ if (ol > 0) {
238
+ for (var i = 0; i < ol; i++) {
239
+ if (typeof objects[i].SetVariable != "undefined") {
240
+ activeObjects[activeObjects.length] = objects[i];
241
+ }
242
+ }
243
+ }
244
+ var embeds = document.getElementsByTagName("embed");
245
+ var el = embeds.length;
246
+ var activeEmbeds = [];
247
+ if (el > 0) {
248
+ for (var j = 0; j < el; j++) {
249
+ if (typeof embeds[j].SetVariable != "undefined") {
250
+ activeEmbeds[activeEmbeds.length] = embeds[j];
251
+ }
252
+ }
253
+ }
254
+ var aol = activeObjects.length;
255
+ var ael = activeEmbeds.length;
256
+ var searchStr = "bridgeName="+ bridgeName;
257
+ if ((aol == 1 && !ael) || (aol == 1 && ael == 1)) {
258
+ FABridge.attachBridge(activeObjects[0], bridgeName);
259
+ }
260
+ else if (ael == 1 && !aol) {
261
+ FABridge.attachBridge(activeEmbeds[0], bridgeName);
262
+ }
263
+ else {
264
+ var flash_found = false;
265
+ if (aol > 1) {
266
+ for (var k = 0; k < aol; k++) {
267
+ var params = activeObjects[k].childNodes;
268
+ for (var l = 0; l < params.length; l++) {
269
+ var param = params[l];
270
+ if (param.nodeType == 1 && param.tagName.toLowerCase() == "param" && param["name"].toLowerCase() == "flashvars" && param["value"].indexOf(searchStr) >= 0) {
271
+ FABridge.attachBridge(activeObjects[k], bridgeName);
272
+ flash_found = true;
273
+ break;
274
+ }
275
+ }
276
+ if (flash_found) {
277
+ break;
278
+ }
279
+ }
280
+ }
281
+ if (!flash_found && ael > 1) {
282
+ for (var m = 0; m < ael; m++) {
283
+ var flashVars = activeEmbeds[m].attributes.getNamedItem("flashVars").nodeValue;
284
+ if (flashVars.indexOf(searchStr) >= 0) {
285
+ FABridge.attachBridge(activeEmbeds[m], bridgeName);
286
+ break;
287
+ }
288
+ }
289
+ }
290
+ }
291
+ return true;
292
+ }
293
+
294
+ // used to track multiple bridge instances, since callbacks from AS are global across the page.
295
+
296
+ FABridge.nextBridgeID = 0;
297
+ FABridge.instances = {};
298
+ FABridge.idMap = {};
299
+ FABridge.refCount = 0;
300
+
301
+ FABridge.extractBridgeFromID = function(id)
302
+ {
303
+ var bridgeID = (id >> 16);
304
+ return FABridge.idMap[bridgeID];
305
+ }
306
+
307
+ FABridge.attachBridge = function(instance, bridgeName)
308
+ {
309
+ var newBridgeInstance = new FABridge(instance, bridgeName);
310
+
311
+ FABridge[bridgeName] = newBridgeInstance;
312
+
313
+ /* FABridge[bridgeName] = function() {
314
+ return newBridgeInstance.root();
315
+ }
316
+ */
317
+ var callbacks = FABridge.initCallbacks[bridgeName];
318
+ if (callbacks == null)
319
+ {
320
+ return;
321
+ }
322
+ for (var i = 0; i < callbacks.length; i++)
323
+ {
324
+ callbacks[i].call(newBridgeInstance);
325
+ }
326
+ delete FABridge.initCallbacks[bridgeName]
327
+ }
328
+
329
+ // some methods can't be proxied. You can use the explicit get,set, and call methods if necessary.
330
+
331
+ FABridge.blockedMethods =
332
+ {
333
+ toString: true,
334
+ get: true,
335
+ set: true,
336
+ call: true
337
+ };
338
+
339
+ FABridge.prototype =
340
+ {
341
+
342
+
343
+ // bootstrapping
344
+
345
+ root: function()
346
+ {
347
+ return this.deserialize(this.target.getRoot());
348
+ },
349
+ //clears all of the AS objects in the cache maps
350
+ releaseASObjects: function()
351
+ {
352
+ return this.target.releaseASObjects();
353
+ },
354
+ //clears a specific object in AS from the type maps
355
+ releaseNamedASObject: function(value)
356
+ {
357
+ if(typeof(value) != "object")
358
+ {
359
+ return false;
360
+ }
361
+ else
362
+ {
363
+ var ret = this.target.releaseNamedASObject(value.fb_instance_id);
364
+ return ret;
365
+ }
366
+ },
367
+ //create a new AS Object
368
+ create: function(className)
369
+ {
370
+ return this.deserialize(this.target.create(className));
371
+ },
372
+
373
+
374
+ // utilities
375
+
376
+ makeID: function(token)
377
+ {
378
+ return (this.bridgeID << 16) + token;
379
+ },
380
+
381
+
382
+ // low level access to the flash object
383
+
384
+ //get a named property from an AS object
385
+ getPropertyFromAS: function(objRef, propName)
386
+ {
387
+ if (FABridge.refCount > 0)
388
+ {
389
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
390
+ }
391
+ else
392
+ {
393
+ FABridge.refCount++;
394
+ retVal = this.target.getPropFromAS(objRef, propName);
395
+ retVal = this.handleError(retVal);
396
+ FABridge.refCount--;
397
+ return retVal;
398
+ }
399
+ },
400
+ //set a named property on an AS object
401
+ setPropertyInAS: function(objRef,propName, value)
402
+ {
403
+ if (FABridge.refCount > 0)
404
+ {
405
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
406
+ }
407
+ else
408
+ {
409
+ FABridge.refCount++;
410
+ retVal = this.target.setPropInAS(objRef,propName, this.serialize(value));
411
+ retVal = this.handleError(retVal);
412
+ FABridge.refCount--;
413
+ return retVal;
414
+ }
415
+ },
416
+
417
+ //call an AS function
418
+ callASFunction: function(funcID, args)
419
+ {
420
+ if (FABridge.refCount > 0)
421
+ {
422
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
423
+ }
424
+ else
425
+ {
426
+ FABridge.refCount++;
427
+ retVal = this.target.invokeASFunction(funcID, this.serialize(args));
428
+ retVal = this.handleError(retVal);
429
+ FABridge.refCount--;
430
+ return retVal;
431
+ }
432
+ },
433
+ //call a method on an AS object
434
+ callASMethod: function(objID, funcName, args)
435
+ {
436
+ if (FABridge.refCount > 0)
437
+ {
438
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
439
+ }
440
+ else
441
+ {
442
+ FABridge.refCount++;
443
+ args = this.serialize(args);
444
+ retVal = this.target.invokeASMethod(objID, funcName, args);
445
+ retVal = this.handleError(retVal);
446
+ FABridge.refCount--;
447
+ return retVal;
448
+ }
449
+ },
450
+
451
+ // responders to remote calls from flash
452
+
453
+ //callback from flash that executes a local JS function
454
+ //used mostly when setting js functions as callbacks on events
455
+ invokeLocalFunction: function(funcID, args)
456
+ {
457
+ var result;
458
+ var func = this.localFunctionCache[funcID];
459
+
460
+ if(func != undefined)
461
+ {
462
+ result = this.serialize(func.apply(null, this.deserialize(args)));
463
+ }
464
+
465
+ return result;
466
+ },
467
+
468
+ // Object Types and Proxies
469
+
470
+ // accepts an object reference, returns a type object matching the obj reference.
471
+ getTypeFromName: function(objTypeName)
472
+ {
473
+ return this.remoteTypeCache[objTypeName];
474
+ },
475
+ //create an AS proxy for the given object ID and type
476
+ createProxy: function(objID, typeName)
477
+ {
478
+ var objType = this.getTypeFromName(typeName);
479
+ instanceFactory.prototype = objType;
480
+ var instance = new instanceFactory(objID);
481
+ this.remoteInstanceCache[objID] = instance;
482
+ return instance;
483
+ },
484
+ //return the proxy associated with the given object ID
485
+ getProxy: function(objID)
486
+ {
487
+ return this.remoteInstanceCache[objID];
488
+ },
489
+
490
+ // accepts a type structure, returns a constructed type
491
+ addTypeDataToCache: function(typeData)
492
+ {
493
+ var newType = new ASProxy(this, typeData.name);
494
+ var accessors = typeData.accessors;
495
+ for (var i = 0; i < accessors.length; i++)
496
+ {
497
+ this.addPropertyToType(newType, accessors[i]);
498
+ }
499
+
500
+ var methods = typeData.methods;
501
+ for (var i = 0; i < methods.length; i++)
502
+ {
503
+ if (FABridge.blockedMethods[methods[i]] == undefined)
504
+ {
505
+ this.addMethodToType(newType, methods[i]);
506
+ }
507
+ }
508
+
509
+
510
+ this.remoteTypeCache[newType.typeName] = newType;
511
+ return newType;
512
+ },
513
+
514
+ //add a property to a typename; used to define the properties that can be called on an AS proxied object
515
+ addPropertyToType: function(ty, propName)
516
+ {
517
+ var c = propName.charAt(0);
518
+ var setterName;
519
+ var getterName;
520
+ if(c >= "a" && c <= "z")
521
+ {
522
+ getterName = "get" + c.toUpperCase() + propName.substr(1);
523
+ setterName = "set" + c.toUpperCase() + propName.substr(1);
524
+ }
525
+ else
526
+ {
527
+ getterName = "get" + propName;
528
+ setterName = "set" + propName;
529
+ }
530
+ ty[setterName] = function(val)
531
+ {
532
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, val);
533
+ }
534
+ ty[getterName] = function()
535
+ {
536
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
537
+ }
538
+ },
539
+
540
+ //add a method to a typename; used to define the methods that can be callefd on an AS proxied object
541
+ addMethodToType: function(ty, methodName)
542
+ {
543
+ ty[methodName] = function()
544
+ {
545
+ return this.bridge.deserialize(this.bridge.callASMethod(this.fb_instance_id, methodName, FABridge.argsToArray(arguments)));
546
+ }
547
+ },
548
+
549
+ // Function Proxies
550
+
551
+ //returns the AS proxy for the specified function ID
552
+ getFunctionProxy: function(funcID)
553
+ {
554
+ var bridge = this;
555
+ if (this.remoteFunctionCache[funcID] == null)
556
+ {
557
+ this.remoteFunctionCache[funcID] = function()
558
+ {
559
+ bridge.callASFunction(funcID, FABridge.argsToArray(arguments));
560
+ }
561
+ }
562
+ return this.remoteFunctionCache[funcID];
563
+ },
564
+
565
+ //reutrns the ID of the given function; if it doesnt exist it is created and added to the local cache
566
+ getFunctionID: function(func)
567
+ {
568
+ if (func.__bridge_id__ == undefined)
569
+ {
570
+ func.__bridge_id__ = this.makeID(this.nextLocalFuncID++);
571
+ this.localFunctionCache[func.__bridge_id__] = func;
572
+ }
573
+ return func.__bridge_id__;
574
+ },
575
+
576
+ // serialization / deserialization
577
+
578
+ serialize: function(value)
579
+ {
580
+ var result = {};
581
+
582
+ var t = typeof(value);
583
+ //primitives are kept as such
584
+ if (t == "number" || t == "string" || t == "boolean" || t == null || t == undefined)
585
+ {
586
+ result = value;
587
+ }
588
+ else if (value instanceof Array)
589
+ {
590
+ //arrays are serializesd recursively
591
+ result = [];
592
+ for (var i = 0; i < value.length; i++)
593
+ {
594
+ result[i] = this.serialize(value[i]);
595
+ }
596
+ }
597
+ else if (t == "function")
598
+ {
599
+ //js functions are assigned an ID and stored in the local cache
600
+ result.type = FABridge.TYPE_JSFUNCTION;
601
+ result.value = this.getFunctionID(value);
602
+ }
603
+ else if (value instanceof ASProxy)
604
+ {
605
+ result.type = FABridge.TYPE_ASINSTANCE;
606
+ result.value = value.fb_instance_id;
607
+ }
608
+ else
609
+ {
610
+ result.type = FABridge.TYPE_ANONYMOUS;
611
+ result.value = value;
612
+ }
613
+
614
+ return result;
615
+ },
616
+
617
+ //on deserialization we always check the return for the specific error code that is used to marshall NPE's into JS errors
618
+ // the unpacking is done by returning the value on each pachet for objects/arrays
619
+ deserialize: function(packedValue)
620
+ {
621
+
622
+ var result;
623
+
624
+ var t = typeof(packedValue);
625
+ if (t == "number" || t == "string" || t == "boolean" || packedValue == null || packedValue == undefined)
626
+ {
627
+ result = this.handleError(packedValue);
628
+ }
629
+ else if (packedValue instanceof Array)
630
+ {
631
+ result = [];
632
+ for (var i = 0; i < packedValue.length; i++)
633
+ {
634
+ result[i] = this.deserialize(packedValue[i]);
635
+ }
636
+ }
637
+ else if (t == "object")
638
+ {
639
+ for(var i = 0; i < packedValue.newTypes.length; i++)
640
+ {
641
+ this.addTypeDataToCache(packedValue.newTypes[i]);
642
+ }
643
+ for (var aRefID in packedValue.newRefs)
644
+ {
645
+ this.createProxy(aRefID, packedValue.newRefs[aRefID]);
646
+ }
647
+ if (packedValue.type == FABridge.TYPE_PRIMITIVE)
648
+ {
649
+ result = packedValue.value;
650
+ }
651
+ else if (packedValue.type == FABridge.TYPE_ASFUNCTION)
652
+ {
653
+ result = this.getFunctionProxy(packedValue.value);
654
+ }
655
+ else if (packedValue.type == FABridge.TYPE_ASINSTANCE)
656
+ {
657
+ result = this.getProxy(packedValue.value);
658
+ }
659
+ else if (packedValue.type == FABridge.TYPE_ANONYMOUS)
660
+ {
661
+ result = packedValue.value;
662
+ }
663
+ }
664
+ return result;
665
+ },
666
+ //increases the reference count for the given object
667
+ addRef: function(obj)
668
+ {
669
+ this.target.incRef(obj.fb_instance_id);
670
+ },
671
+ //decrease the reference count for the given object and release it if needed
672
+ release:function(obj)
673
+ {
674
+ this.target.releaseRef(obj.fb_instance_id);
675
+ },
676
+
677
+ // check the given value for the components of the hard-coded error code : __FLASHERROR
678
+ // used to marshall NPE's into flash
679
+
680
+ handleError: function(value)
681
+ {
682
+ if (typeof(value)=="string" && value.indexOf("__FLASHERROR")==0)
683
+ {
684
+ var myErrorMessage = value.split("||");
685
+ if(FABridge.refCount > 0 )
686
+ {
687
+ FABridge.refCount--;
688
+ }
689
+ throw new Error(myErrorMessage[1]);
690
+ return value;
691
+ }
692
+ else
693
+ {
694
+ return value;
695
+ }
696
+ }
697
+ };
698
+
699
+ // The root ASProxy class that facades a flash object
700
+
701
+ ASProxy = function(bridge, typeName)
702
+ {
703
+ this.bridge = bridge;
704
+ this.typeName = typeName;
705
+ return this;
706
+ };
707
+ //methods available on each ASProxy object
708
+ ASProxy.prototype =
709
+ {
710
+ get: function(propName)
711
+ {
712
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
713
+ },
714
+
715
+ set: function(propName, value)
716
+ {
717
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, value);
718
+ },
719
+
720
+ call: function(funcName, args)
721
+ {
722
+ this.bridge.callASMethod(this.fb_instance_id, funcName, args);
723
+ },
724
+
725
+ addRef: function() {
726
+ this.bridge.addRef(this);
727
+ },
728
+
729
+ release: function() {
730
+ this.bridge.release(this);
731
+ }
732
+ };
733
+
734
+ // Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
735
+ // License: New BSD License
736
+ // Reference: http://dev.w3.org/html5/websockets/
737
+ // Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
738
+
739
+ (function() {
740
+
741
+ if (window.WebSocket) return;
742
+
743
+ var console = window.console;
744
+ if (!console) console = {log: function(){ }, error: function(){ }};
745
+
746
+ if (!swfobject.hasFlashPlayerVersion("9.0.0")) {
747
+ console.error("Flash Player is not installed.");
748
+ return;
749
+ }
750
+ if (location.protocol == "file:") {
751
+ console.error(
752
+ "WARNING: web-socket-js doesn't work in file:///... URL " +
753
+ "unless you set Flash Security Settings properly. " +
754
+ "Open the page via Web server i.e. http://...");
755
+ }
756
+
757
+ WebSocket = function(url, protocol, proxyHost, proxyPort, headers) {
758
+ var self = this;
759
+ self.readyState = WebSocket.CONNECTING;
760
+ self.bufferedAmount = 0;
761
+ // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
762
+ // Otherwise, when onopen fires immediately, onopen is called before it is set.
763
+ setTimeout(function() {
764
+ WebSocket.__addTask(function() {
765
+ self.__createFlash(url, protocol, proxyHost, proxyPort, headers);
766
+ });
767
+ }, 1);
768
+ }
769
+
770
+ WebSocket.prototype.__createFlash = function(url, protocol, proxyHost, proxyPort, headers) {
771
+ var self = this;
772
+ self.__flash =
773
+ WebSocket.__flash.create(url, protocol, proxyHost || null, proxyPort || 0, headers || null);
774
+
775
+ self.__flash.addEventListener("open", function(fe) {
776
+ try {
777
+ self.readyState = self.__flash.getReadyState();
778
+ if (self.__timer) clearInterval(self.__timer);
779
+ if (window.opera) {
780
+ // Workaround for weird behavior of Opera which sometimes drops events.
781
+ self.__timer = setInterval(function () {
782
+ self.__handleMessages();
783
+ }, 500);
784
+ }
785
+ if (self.onopen) self.onopen();
786
+ } catch (e) {
787
+ console.error(e.toString());
788
+ }
789
+ });
790
+
791
+ self.__flash.addEventListener("close", function(fe) {
792
+ try {
793
+ self.readyState = self.__flash.getReadyState();
794
+ if (self.__timer) clearInterval(self.__timer);
795
+ if (self.onclose) self.onclose();
796
+ } catch (e) {
797
+ console.error(e.toString());
798
+ }
799
+ });
800
+
801
+ self.__flash.addEventListener("message", function() {
802
+ try {
803
+ self.__handleMessages();
804
+ } catch (e) {
805
+ console.error(e.toString());
806
+ }
807
+ });
808
+
809
+ self.__flash.addEventListener("error", function(fe) {
810
+ try {
811
+ if (self.__timer) clearInterval(self.__timer);
812
+ if (self.onerror) self.onerror();
813
+ } catch (e) {
814
+ console.error(e.toString());
815
+ }
816
+ });
817
+
818
+ self.__flash.addEventListener("stateChange", function(fe) {
819
+ try {
820
+ self.readyState = self.__flash.getReadyState();
821
+ self.bufferedAmount = fe.getBufferedAmount();
822
+ } catch (e) {
823
+ console.error(e.toString());
824
+ }
825
+ });
826
+
827
+ //console.log("[WebSocket] Flash object is ready");
828
+ };
829
+
830
+ WebSocket.prototype.send = function(data) {
831
+ if (this.__flash) {
832
+ this.readyState = this.__flash.getReadyState();
833
+ }
834
+ if (!this.__flash || this.readyState == WebSocket.CONNECTING) {
835
+ throw "INVALID_STATE_ERR: Web Socket connection has not been established";
836
+ }
837
+ // We use encodeURIComponent() here, because FABridge doesn't work if
838
+ // the argument includes some characters. We don't use escape() here
839
+ // because of this:
840
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
841
+ // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
842
+ // preserve all Unicode characters either e.g. "\uffff" in Firefox.
843
+ var result = this.__flash.send(encodeURIComponent(data));
844
+ if (result < 0) { // success
845
+ return true;
846
+ } else {
847
+ this.bufferedAmount = result;
848
+ return false;
849
+ }
850
+ };
851
+
852
+ WebSocket.prototype.close = function() {
853
+ var self = this;
854
+ if (!self.__flash) return;
855
+ self.readyState = self.__flash.getReadyState();
856
+ if (self.readyState == WebSocket.CLOSED || self.readyState == WebSocket.CLOSING) return;
857
+ self.__flash.close();
858
+ // Sets/calls them manually here because Flash WebSocketConnection.close cannot fire events
859
+ // which causes weird error:
860
+ // > You are trying to call recursively into the Flash Player which is not allowed.
861
+ self.readyState = WebSocket.CLOSED;
862
+ if (self.__timer) clearInterval(self.__timer);
863
+ if (self.onclose) {
864
+ // Make it asynchronous so that it looks more like an actual
865
+ // close event
866
+ setTimeout(self.onclose, 1);
867
+ }
868
+ };
869
+
870
+ /**
871
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
872
+ *
873
+ * @param {string} type
874
+ * @param {function} listener
875
+ * @param {boolean} useCapture !NB Not implemented yet
876
+ * @return void
877
+ */
878
+ WebSocket.prototype.addEventListener = function(type, listener, useCapture) {
879
+ if (!('__events' in this)) {
880
+ this.__events = {};
881
+ }
882
+ if (!(type in this.__events)) {
883
+ this.__events[type] = [];
884
+ if ('function' == typeof this['on' + type]) {
885
+ this.__events[type].defaultHandler = this['on' + type];
886
+ this['on' + type] = this.__createEventHandler(this, type);
887
+ }
888
+ }
889
+ this.__events[type].push(listener);
890
+ };
891
+
892
+ /**
893
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
894
+ *
895
+ * @param {string} type
896
+ * @param {function} listener
897
+ * @param {boolean} useCapture NB! Not implemented yet
898
+ * @return void
899
+ */
900
+ WebSocket.prototype.removeEventListener = function(type, listener, useCapture) {
901
+ if (!('__events' in this)) {
902
+ this.__events = {};
903
+ }
904
+ if (!(type in this.__events)) return;
905
+ for (var i = this.__events.length; i > -1; --i) {
906
+ if (listener === this.__events[type][i]) {
907
+ this.__events[type].splice(i, 1);
908
+ break;
909
+ }
910
+ }
911
+ };
912
+
913
+ /**
914
+ * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
915
+ *
916
+ * @param {WebSocketEvent} event
917
+ * @return void
918
+ */
919
+ WebSocket.prototype.dispatchEvent = function(event) {
920
+ if (!('__events' in this)) throw 'UNSPECIFIED_EVENT_TYPE_ERR';
921
+ if (!(event.type in this.__events)) throw 'UNSPECIFIED_EVENT_TYPE_ERR';
922
+
923
+ for (var i = 0, l = this.__events[event.type].length; i < l; ++ i) {
924
+ this.__events[event.type][i](event);
925
+ if (event.cancelBubble) break;
926
+ }
927
+
928
+ if (false !== event.returnValue &&
929
+ 'function' == typeof this.__events[event.type].defaultHandler)
930
+ {
931
+ this.__events[event.type].defaultHandler(event);
932
+ }
933
+ };
934
+
935
+ WebSocket.prototype.__handleMessages = function() {
936
+ // Gets data using readSocketData() instead of getting it from event object
937
+ // of Flash event. This is to make sure to keep message order.
938
+ // It seems sometimes Flash events don't arrive in the same order as they are sent.
939
+ var arr = this.__flash.readSocketData();
940
+ for (var i = 0; i < arr.length; i++) {
941
+ var data = decodeURIComponent(arr[i]);
942
+ try {
943
+ if (this.onmessage) {
944
+ var e;
945
+ if (window.MessageEvent && !window.opera) {
946
+ e = document.createEvent("MessageEvent");
947
+ e.initMessageEvent("message", false, false, data, null, null, window, null);
948
+ } else { // IE and Opera, the latter one truncates the data parameter after any 0x00 bytes
949
+ e = {data: data};
950
+ }
951
+ this.onmessage(e);
952
+ }
953
+ } catch (e) {
954
+ console.error(e.toString());
955
+ }
956
+ }
957
+ };
958
+
959
+ /**
960
+ * @param {object} object
961
+ * @param {string} type
962
+ */
963
+ WebSocket.prototype.__createEventHandler = function(object, type) {
964
+ return function(data) {
965
+ var event = new WebSocketEvent();
966
+ event.initEvent(type, true, true);
967
+ event.target = event.currentTarget = object;
968
+ for (var key in data) {
969
+ event[key] = data[key];
970
+ }
971
+ object.dispatchEvent(event, arguments);
972
+ };
973
+ }
974
+
975
+ /**
976
+ * Basic implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface">DOM 2 EventInterface</a>}
977
+ *
978
+ * @class
979
+ * @constructor
980
+ */
981
+ function WebSocketEvent(){}
982
+
983
+ /**
984
+ *
985
+ * @type boolean
986
+ */
987
+ WebSocketEvent.prototype.cancelable = true;
988
+
989
+ /**
990
+ *
991
+ * @type boolean
992
+ */
993
+ WebSocketEvent.prototype.cancelBubble = false;
994
+
995
+ /**
996
+ *
997
+ * @return void
998
+ */
999
+ WebSocketEvent.prototype.preventDefault = function() {
1000
+ if (this.cancelable) {
1001
+ this.returnValue = false;
1002
+ }
1003
+ };
1004
+
1005
+ /**
1006
+ *
1007
+ * @return void
1008
+ */
1009
+ WebSocketEvent.prototype.stopPropagation = function() {
1010
+ this.cancelBubble = true;
1011
+ };
1012
+
1013
+ /**
1014
+ *
1015
+ * @param {string} eventTypeArg
1016
+ * @param {boolean} canBubbleArg
1017
+ * @param {boolean} cancelableArg
1018
+ * @return void
1019
+ */
1020
+ WebSocketEvent.prototype.initEvent = function(eventTypeArg, canBubbleArg, cancelableArg) {
1021
+ this.type = eventTypeArg;
1022
+ this.cancelable = cancelableArg;
1023
+ this.timeStamp = new Date();
1024
+ };
1025
+
1026
+
1027
+ WebSocket.CONNECTING = 0;
1028
+ WebSocket.OPEN = 1;
1029
+ WebSocket.CLOSING = 2;
1030
+ WebSocket.CLOSED = 3;
1031
+
1032
+ WebSocket.__tasks = [];
1033
+
1034
+ WebSocket.__initialize = function() {
1035
+ if (WebSocket.__swfLocation) {
1036
+ // For backword compatibility.
1037
+ window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
1038
+ }
1039
+ if (!window.WEB_SOCKET_SWF_LOCATION) {
1040
+ console.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
1041
+ return;
1042
+ }
1043
+ var container = document.createElement("div");
1044
+ container.id = "webSocketContainer";
1045
+ // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
1046
+ // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
1047
+ // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
1048
+ // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
1049
+ // the best we can do as far as we know now.
1050
+ container.style.position = "absolute";
1051
+ if (WebSocket.__isFlashLite()) {
1052
+ container.style.left = "0px";
1053
+ container.style.top = "0px";
1054
+ } else {
1055
+ container.style.left = "-100px";
1056
+ container.style.top = "-100px";
1057
+ }
1058
+ var holder = document.createElement("div");
1059
+ holder.id = "webSocketFlash";
1060
+ container.appendChild(holder);
1061
+ document.body.appendChild(container);
1062
+ // See this article for hasPriority:
1063
+ // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
1064
+ swfobject.embedSWF(
1065
+ WEB_SOCKET_SWF_LOCATION, "webSocketFlash",
1066
+ "1" /* width */, "1" /* height */, "9.0.0" /* SWF version */,
1067
+ null, {bridgeName: "webSocket"}, {hasPriority: true, allowScriptAccess: "always"}, null,
1068
+ function(e) {
1069
+ if (!e.success) console.error("[WebSocket] swfobject.embedSWF failed");
1070
+ }
1071
+ );
1072
+ FABridge.addInitializationCallback("webSocket", function() {
1073
+ try {
1074
+ //console.log("[WebSocket] FABridge initializad");
1075
+ WebSocket.__flash = FABridge.webSocket.root();
1076
+ WebSocket.__flash.setCallerUrl(location.href);
1077
+ WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);
1078
+ for (var i = 0; i < WebSocket.__tasks.length; ++i) {
1079
+ WebSocket.__tasks[i]();
1080
+ }
1081
+ WebSocket.__tasks = [];
1082
+ } catch (e) {
1083
+ console.error("[WebSocket] " + e.toString());
1084
+ }
1085
+ });
1086
+ };
1087
+
1088
+ WebSocket.__addTask = function(task) {
1089
+ if (WebSocket.__flash) {
1090
+ task();
1091
+ } else {
1092
+ WebSocket.__tasks.push(task);
1093
+ }
1094
+ };
1095
+
1096
+ WebSocket.__isFlashLite = function() {
1097
+ if (!window.navigator || !window.navigator.mimeTypes) return false;
1098
+ var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
1099
+ if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) return false;
1100
+ return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
1101
+ };
1102
+
1103
+ // called from Flash
1104
+ window.webSocketLog = function(message) {
1105
+ console.log(decodeURIComponent(message));
1106
+ };
1107
+
1108
+ // called from Flash
1109
+ window.webSocketError = function(message) {
1110
+ console.error(decodeURIComponent(message));
1111
+ };
1112
+
1113
+ if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
1114
+ if (window.addEventListener) {
1115
+ window.addEventListener("load", WebSocket.__initialize, false);
1116
+ } else {
1117
+ window.attachEvent("onload", WebSocket.__initialize);
1118
+ }
1119
+ }
1120
+
1121
+ })();
1122
+