PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/flash/flash-embed.js

https://bitbucket.org/cng1985/kissy
JavaScript | 364 lines | 351 code | 9 blank | 4 comment | 0 complexity | c343f7bd8257496e963e1c4048ce9d81 MD5 | raw file
  1. /**
  2. * @module 将 swf 嵌入到页面中
  3. * @author kingfo<oicuicu@gmail.com>, 射雕<lifesinger@gmail.com>
  4. */
  5. KISSY.add('flash-embed', function(S) {
  6. var UA = S.UA, DOM = S.DOM, Flash = S.Flash,
  7. SWF_SUCCESS = 1,
  8. FP_LOW = 0,
  9. FP_UNINSTALL = -1,
  10. TARGET_NOT_FOUND = -2, // 指定 ID 的对象未找到
  11. SWF_SRC_UNDEFINED = -3, // swf 的地址未指定
  12. RE_FLASH_TAGS = /^(?:object|embed)/i,
  13. CID = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
  14. TYPE = 'application/x-shockwave-flash',
  15. FLASHVARS = 'flashvars', EMPTY = '', SPACE =' ',
  16. PREFIX = 'ks-flash-', ID_PRE = '#', EQUAL = '=', DQUOTA ='"', SQUOTA = "'", LT ='<', GT='>',
  17. CONTAINER_PRE = 'ks-flash-container-',
  18. OBJECT_TAG = 'object',
  19. EMBED_TAG = 'embed',
  20. OP = Object.prototype,
  21. encode = encodeURIComponent,
  22. // flash player 的参数范围
  23. PARAMS = {
  24. ////////////////////////// 高频率使用的参数
  25. //flashvars: EMPTY, // swf 传入的第三方数据。支持复杂的 Object / XML 数据 / JSON 字符串
  26. wmode: EMPTY,
  27. allowscriptaccess: EMPTY,
  28. allownetworking: EMPTY,
  29. allowfullscreen: EMPTY,
  30. ///////////////////////// 显示 控制 删除
  31. play: 'false',
  32. loop: EMPTY,
  33. menu: EMPTY,
  34. quality: EMPTY,
  35. scale: EMPTY,
  36. salign: EMPTY,
  37. bgcolor: EMPTY,
  38. devicefont: EMPTY,
  39. ///////////////////////// 其他控制参数
  40. base: EMPTY,
  41. swliveconnect: EMPTY,
  42. seamlesstabbing: EMPTY
  43. },
  44. defaultConifg = {
  45. //src: '', // swf 路径
  46. params: { }, // Flash Player 的配置参数
  47. attrs: { // swf 对应 DOM 元素的属性
  48. width: 215, // 最小控制面板宽度,小于此数字将无法支持在线快速安装
  49. height: 138 // 最小控制面板高度,小于此数字将无法支持在线快速安装
  50. },
  51. //xi: '', // 快速安装地址。全称 express install // ? 默认路径
  52. version: 9 // 要求的 Flash Player 最低版本
  53. };
  54. S.mix(Flash, {
  55. fpv: UA.fpv,
  56. fpvGEQ: UA.fpvGEQ,
  57. /**
  58. * 添加 SWF 对象
  59. * @param target {String|HTMLElement} #id or element
  60. */
  61. add: function(target, config, callback) {
  62. var xi, id , isDynamic, nodeName;
  63. // 标准化配置信息
  64. config = Flash._normalize(config);
  65. // 合并配置信息
  66. config = S.merge(defaultConifg, config);
  67. config.attrs = S.merge(defaultConifg.attrs, config.attrs);
  68. id = target.replace(ID_PRE, '');
  69. // 1. target 元素未找到 则自行创建一个容器
  70. if (!(target = S.get(target))) {
  71. target = DOM.create('<div id='+ id +'>');
  72. document.body.appendChild(target);
  73. }
  74. nodeName = target.nodeName.toLowerCase();
  75. // 动态标记 供后续扩展使用
  76. // 在 callback(config) 的 config.dynamic 应用
  77. isDynamic = !RE_FLASH_TAGS.test(nodeName);
  78. // 保存 容器id, 没有则自动生成
  79. if (!target.id) target.id = S.guid(CONTAINER_PRE);
  80. id = target.id;
  81. // 保存 Flash id , 没有则自动生成
  82. if (!config.id) config.id = S.guid(PREFIX);
  83. config.attrs.id = config.id;
  84. // 2. flash 插件没有安装
  85. if (!UA.fpv()) {
  86. Flash._callback(callback, FP_UNINSTALL, id, target,isDynamic);
  87. return;
  88. }
  89. // 3. 已安装,但当前客户端版本低于指定版本时
  90. if (!UA.fpvGEQ(config.version)) {
  91. Flash._callback(callback, FP_LOW, id, target,isDynamic);
  92. // 有 xi 时,将 src 替换为快速安装
  93. if (!((xi = config.xi) && S.isString(xi))) return;
  94. config.src = xi;
  95. }
  96. // 对已有 HTML 结构的 SWF 进行注册使用
  97. if(!isDynamic){
  98. // bugfix: 静态双 object 获取问题。双 Object 外层有 id 但内部才有效。 longzang 2010/8/9
  99. if (nodeName == OBJECT_TAG) {
  100. // bugfix: 静态双 object 在 chrome 7以下存在问题,如使用 chrome 内胆的 sogou。2010/12/23
  101. if (UA.gecko || UA.opera || UA.chrome > 7) {
  102. target = S.query('object', target)[0] || target;
  103. }
  104. }
  105. config.attrs.id = id;
  106. Flash._register(target, config, callback,isDynamic);
  107. return;
  108. }
  109. // src 未指定
  110. if (!config.src) {
  111. Flash._callback(callback, SWF_SRC_UNDEFINED, id, target,isDynamic);
  112. return;
  113. }
  114. // 替换 target 为 SWF 嵌入对象
  115. Flash._embed(target, config, callback);
  116. },
  117. /**
  118. * 获得已注册到 S.Flash 的 SWF
  119. * 注意,请不要混淆 DOM.get() 和 Flash.get()
  120. * 只有成功执行过 S.Flash.add() 的 SWF 才可以被获取
  121. * @return {HTMLElement} 返回 SWF 的 HTML 元素(object/embed). 未注册时,返回 undefined
  122. */
  123. get: function(id) {
  124. return Flash.swfs[id];
  125. },
  126. /**
  127. * 移除已注册到 S.Flash 的 SWF 和 DOM 中对应的 HTML 元素
  128. */
  129. remove: function(id) {
  130. var swf = Flash.get(id);
  131. if (swf) {
  132. DOM.remove(swf);
  133. delete Flash.swfs[swf.id];
  134. Flash.length -= 1;
  135. }
  136. },
  137. /**
  138. * 检测是否存在已注册的 swf
  139. * 只有成功执行过 S.Flash.add() 的 SWF 才可以被获取到
  140. * @return {Boolean}
  141. */
  142. contains: function(target) {
  143. var swfs = Flash.swfs,
  144. id, ret = false;
  145. if (S.isString(target)) {
  146. ret = (target in swfs);
  147. } else {
  148. for (id in swfs)
  149. if (swfs[id] === target) {
  150. ret = true;
  151. break;
  152. }
  153. }
  154. return ret;
  155. },
  156. _register: function(swf, config, callback,isDynamic) {;
  157. var id = config.attrs.id;
  158. Flash._addSWF(id, swf);
  159. Flash._callback(callback, SWF_SUCCESS, id, swf,isDynamic);
  160. },
  161. _embed: function (target, config, callback) {
  162. var o = Flash._stringSWF(config);
  163. target.innerHTML = o;
  164. // bugfix: 重新获取对象,否则还是老对象. 如 入口为 div 如果不重新获取则仍然是 div longzang | 2010/8/9
  165. target = S.get(ID_PRE + config.id);
  166. Flash._register(target, config, callback,true);
  167. },
  168. _callback: function(callback, type, id, swf,isDynamic) {
  169. if (type && S.isFunction(callback)) {
  170. callback({
  171. status: type,
  172. id: id,
  173. swf: swf,
  174. dynamic:!!isDynamic
  175. });
  176. }
  177. },
  178. _addSWF: function(id, swf) {
  179. if (id && swf) {
  180. Flash.swfs[id] = swf;
  181. Flash.length += 1;
  182. }
  183. },
  184. _stringSWF:function (config){
  185. var res,
  186. attr = EMPTY,
  187. par = EMPTY,
  188. src = config.src,
  189. attrs = config.attrs,
  190. params = config.params,
  191. id,k,v,tag;
  192. if(UA.ie){
  193. // 创建 object
  194. tag = OBJECT_TAG;
  195. // 普通属性
  196. for (k in attrs){
  197. if(attrs[k] != OP[k]){ // 过滤原型属性
  198. if(k != "classid" && k != "data") attr += stringAttr(k,attrs[k]);
  199. }
  200. }
  201. // 特殊属性
  202. attr += stringAttr('classid',CID);
  203. // 普通参数
  204. for (k in params){
  205. if(k in PARAMS) par += stringParam(k,params[k]);
  206. }
  207. par += stringParam('movie',src);
  208. // 特殊参数
  209. if(params[FLASHVARS]) par += stringParam(FLASHVARS,Flash.toFlashVars(params[FLASHVARS]));
  210. res = LT + tag + attr + GT + par + LT + '/' + tag + GT;
  211. }else{
  212. // 创建 embed
  213. tag = EMBED_TAG;
  214. // 源
  215. attr += stringAttr('src',src);
  216. // 普通属性
  217. for (k in attrs){
  218. if(attrs[k] != OP[k]){
  219. if(k != "classid" && k != "data") attr += stringAttr(k,attrs[k]);
  220. }
  221. }
  222. // 特殊属性
  223. attr += stringAttr('type',TYPE);
  224. // 参数属性
  225. for (k in params){
  226. if(k in PARAMS) par += stringAttr(k,params[k]);
  227. }
  228. // 特殊参数
  229. if(params[FLASHVARS]) par += stringAttr(FLASHVARS,Flash.toFlashVars(params[FLASHVARS]));
  230. res = LT + tag + attr + par + '/' + GT;
  231. }
  232. return res
  233. },
  234. /**
  235. * 将对象的 key 全部转为小写
  236. * 一般用于配置选项 key 的标准化
  237. */
  238. _normalize: function(obj) {
  239. var key, val, prop, ret = obj || { };
  240. if (S.isPlainObject(obj)) {
  241. ret = {};
  242. for (prop in obj) {
  243. key = prop.toLowerCase();
  244. val = obj[prop];
  245. // 忽略自定义传参内容标准化
  246. if (key !== FLASHVARS) val = Flash._normalize(val);
  247. ret[key] = val;
  248. }
  249. }
  250. return ret;
  251. },
  252. /**
  253. * 将普通对象转换为 flashvars
  254. * eg: {a: 1, b: { x: 2, z: 's=1&c=2' }} => a=1&b={"x":2,"z":"s%3D1%26c%3D2"}
  255. */
  256. toFlashVars: function(obj) {
  257. if (!S.isPlainObject(obj)) return EMPTY; // 仅支持 PlainOject
  258. var prop, data, arr = [],ret;
  259. for (prop in obj) {
  260. data = obj[prop];
  261. // 字符串,用双引号括起来 [bug]不需要 longzang
  262. if (S.isString(data)) {
  263. //data = '"' + encode(data) + '"';
  264. data = encode(data); //bugfix: 有些值事实上不需要双引号 longzang 2010/8/4
  265. }
  266. // 其它值,用 stringify 转换后,再转义掉字符串值
  267. else {
  268. data = (S.JSON.stringify(data));
  269. if (!data) continue; // 忽略掉 undefined, fn 等值
  270. data = data.replace(/:"([^"]+)/g, function(m, val) {
  271. return ':"' + encode(val);
  272. });
  273. }
  274. arr.push(prop + '=' + data);
  275. }
  276. ret = arr.join('&');
  277. return ret.replace(/"/g,"'"); //bugfix: 将 " 替换为 ',以免取值产生问题 但注意自转换为JSON时需要进行还原处理
  278. }
  279. });
  280. function stringAttr(key,value){
  281. return SPACE + key + EQUAL + DQUOTA + value + DQUOTA;;
  282. }
  283. function stringParam(key,value){
  284. return '<param name="' + key + '" value="' + value + '" />';
  285. }
  286. }, { host: 'flash' });