1 /** 2 * simplified flash bridge for yui swf 3 * @author yiminghe@gmail.com 4 */ 5 KISSY.add("editor/plugin/flashBridge/index", function (S, Editor, flashUtils) { 6 7 var instances = {}; 8 9 function FlashBridge(cfg) { 10 this._init(cfg); 11 } 12 13 S.augment(FlashBridge, S.EventTarget, { 14 _init:function (cfg) { 15 var self = this, 16 id = S.guid("flashbridge-"), 17 callback = "KISSY.Editor.FlashBridge.EventHandler"; 18 cfg.flashVars = cfg.flashVars || {}; 19 cfg.attrs = cfg.attrs || {}; 20 cfg.params = cfg.params || {}; 21 var flashVars = cfg.flashVars, 22 attrs = cfg.attrs, 23 params = cfg.params; 24 S.mix(attrs, { 25 id:id, 26 //http://yiminghe.javaeye.com/blog/764872 27 //firefox 必须使创建的flash以及容器可见,才会触发contentReady 28 //默认给flash自身很大的宽高,容器小点就可以了, 29 width:'100%', 30 height:'100%' 31 }, false); 32 //这几个要放在 param 里面,主要是允许 flash js沟通 33 S.mix(params, { 34 allowScriptAccess:'always', 35 allowNetworking:'all', 36 scale:'noScale' 37 }, false); 38 S.mix(flashVars, { 39 shareData:false, 40 useCompression:false 41 }, false); 42 var swfCore = { 43 YUISwfId:id, 44 YUIBridgeCallback:callback 45 }; 46 if (cfg.ajbridge) { 47 swfCore = { 48 swfID:id, 49 jsEntry:callback 50 }; 51 } 52 S.mix(flashVars, swfCore); 53 instances[id] = self; 54 self.id = id; 55 self.swf = flashUtils.createSWFRuntime(cfg.movie, cfg); 56 self._expose(cfg.methods); 57 }, 58 _expose:function (methods) { 59 var self = this; 60 for (var i = 0; i < methods.length; i++) { 61 var m = methods[i]; 62 (function (m) { 63 self[m] = function () { 64 return self._callSWF(m, S.makeArray(arguments)); 65 }; 66 })(m); 67 } 68 }, 69 /** 70 * Calls a specific function exposed by the SWF's ExternalInterface. 71 * @param func {String} the name of the function to call 72 * @param args {Array} the set of arguments to pass to the function. 73 */ 74 _callSWF:function (func, args) { 75 var self = this; 76 args = args || []; 77 try { 78 if (self.swf[func]) { 79 return self.swf[func].apply(self.swf, args); 80 } 81 } 82 // some version flash function is odd in ie: property or method not supported by object 83 catch (e) { 84 var params = ""; 85 if (args.length !== 0) { 86 params = "'" + args.join("', '") + "'"; 87 } 88 //avoid eval for compressiong 89 return (new Function('self', 'return self.swf.' + func + '(' + params + ');'))(self); 90 } 91 }, 92 _eventHandler:function (event) { 93 var self = this, 94 type = event.type; 95 96 if (type === 'log') { 97 S.log(event.message); 98 } else if (type) { 99 self.fire(type, event); 100 } 101 }, 102 ready:function (fn) { 103 var self = this; 104 if (self._ready) { 105 fn.call(this); 106 } else { 107 self.on("contentReady", fn); 108 } 109 }, 110 destroy:function () { 111 delete instances[this.id]; 112 } 113 }); 114 115 FlashBridge.EventHandler = function (id, event) { 116 S.log("flash fire event : " + event.type); 117 var instance = instances[id]; 118 if (instance) { 119 //防止ie同步触发事件,后面还没on呢,另外给 swf 喘息机会 120 //否则同步后触发事件,立即调用swf方法会出错 121 setTimeout(function () { 122 instance._eventHandler.call(instance, event); 123 }, 100); 124 } 125 }; 126 127 Editor.FlashBridge = FlashBridge; 128 129 var UA = S.UA, fpv, fpvF, firstRun = true; 130 131 /* 132 获取 Flash 版本号 133 返回数据 [M, S, R] 若未安装,则返回 undefined 134 */ 135 function getFlashVersion() { 136 var ver, SF = 'ShockwaveFlash'; 137 138 // for NPAPI see: http://en.wikipedia.org/wiki/NPAPI 139 if (navigator.plugins && navigator.mimeTypes.length) { 140 ver = (navigator.plugins['Shockwave Flash'] || {})['description']; 141 } 142 // for ActiveX see: http://en.wikipedia.org/wiki/ActiveX 143 else if (window.ActiveXObject) { 144 try { 145 ver = new ActiveXObject(SF + '.' + SF)['GetVariable']('$version'); 146 } catch (ex) { 147 //S.log('getFlashVersion failed via ActiveXObject'); 148 // nothing to do, just return undefined 149 } 150 } 151 152 // 插件没安装或有问题时,ver 为 undefined 153 if (!ver) return undefined; 154 155 // 插件安装正常时,ver 为 "Shockwave Flash 10.1 r53" or "WIN 10,1,53,64" 156 return arrify(ver); 157 } 158 159 /* 160 arrify("10.1.r53") => ["10", "1", "53"] 161 */ 162 function arrify(ver) { 163 return ver.match(/(\d)+/g); 164 } 165 166 /* 167 格式:主版本号Major.次版本号Minor(小数点后3位,占3位)修正版本号Revision(小数点后第4至第8位,占5位) 168 ver 参数不符合预期时,返回 0 169 numerify("10.1 r53") => 10.00100053 170 numerify(["10", "1", "53"]) => 10.00100053 171 numerify(12.2) => 12.2 172 */ 173 function numerify(ver) { 174 var arr = S.isString(ver) ? arrify(ver) : ver, ret = ver; 175 if (S.isArray(arr)) { 176 ret = parseFloat(arr[0] + '.' + pad(arr[1], 3) + pad(arr[2], 5)); 177 } 178 return ret || 0; 179 } 180 181 /* 182 pad(12, 5) => "00012" 183 ref: http://lifesinger.org/blog/2009/08/the-harm-of-tricky-code/ 184 */ 185 function pad(num, n) { 186 var len = (num + '').length; 187 while (len++ < n) { 188 num = '0' + num; 189 } 190 return num; 191 } 192 193 /* 194 返回数据 [M, S, R] 若未安装,则返回 undefined 195 fpv 全称是 flash player version 196 */ 197 UA.fpv = function (force) { 198 // 考虑 new ActiveX 和 try catch 的 性能损耗,延迟初始化到第一次调用时 199 if (force || firstRun) { 200 firstRun = false; 201 fpv = getFlashVersion(); 202 fpvF = numerify(fpv); 203 } 204 return fpv; 205 }; 206 207 /* 208 Checks fpv is greater than or equal the specific version. 209 普通的 flash 版本检测推荐使用该方法 210 @param ver eg. "10.1.53" 211 <code> 212 if(S.UA.fpvGEQ('9.9.2')) { ... } 213 </code> 214 */ 215 UA.fpvGEQ = function (ver, force) { 216 if (firstRun) UA.fpv(force); 217 return !!fpvF && (fpvF >= numerify(ver)); 218 }; 219 220 return FlashBridge; 221 222 }, { 223 requires:['editor', '../flashCommon/utils'] 224 });