tangram.js 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. // Copyright (c) 2009, Baidu Inc. All rights reserved.
  2. //
  3. // Licensed under the BSD License
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http:// tangram.baidu.com/license.html
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @namespace T Tangram七巧板
  16. * @name T
  17. * @version 1.6.0
  18. */
  19. /**
  20. * 声明baidu包
  21. * @author: allstar, erik, meizz, berg
  22. */
  23. var T,
  24. baidu = T = baidu || {version: "1.5.0"};
  25. baidu.guid = "$BAIDU$";
  26. baidu.$$ = window[baidu.guid] = window[baidu.guid] || {global:{}};
  27. /**
  28. * 使用flash资源封装的一些功能
  29. * @namespace baidu.flash
  30. */
  31. baidu.flash = baidu.flash || {};
  32. /**
  33. * 操作dom的方法
  34. * @namespace baidu.dom
  35. */
  36. baidu.dom = baidu.dom || {};
  37. /**
  38. * 从文档中获取指定的DOM元素
  39. * @name baidu.dom.g
  40. * @function
  41. * @grammar baidu.dom.g(id)
  42. * @param {string|HTMLElement} id 元素的id或DOM元素.
  43. * @shortcut g,T.G
  44. * @meta standard
  45. * @see baidu.dom.q
  46. *
  47. * @return {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数.
  48. */
  49. baidu.dom.g = function(id) {
  50. if (!id) return null;
  51. if ('string' == typeof id || id instanceof String) {
  52. return document.getElementById(id);
  53. } else if (id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  54. return id;
  55. }
  56. return null;
  57. };
  58. baidu.g = baidu.G = baidu.dom.g;
  59. /**
  60. * 操作数组的方法
  61. * @namespace baidu.array
  62. */
  63. baidu.array = baidu.array || {};
  64. /**
  65. * 遍历数组中所有元素
  66. * @name baidu.array.each
  67. * @function
  68. * @grammar baidu.array.each(source, iterator[, thisObject])
  69. * @param {Array} source 需要遍历的数组
  70. * @param {Function} iterator 对每个数组元素进行调用的函数,该函数有两个参数,第一个为数组元素,第二个为数组索引值,function (item, index)。
  71. * @param {Object} [thisObject] 函数调用时的this指针,如果没有此参数,默认是当前遍历的数组
  72. * @remark
  73. * each方法不支持对Object的遍历,对Object的遍历使用baidu.object.each 。
  74. * @shortcut each
  75. * @meta standard
  76. *
  77. * @returns {Array} 遍历的数组
  78. */
  79. baidu.each = baidu.array.forEach = baidu.array.each = function (source, iterator, thisObject) {
  80. var returnValue, item, i, len = source.length;
  81. if ('function' == typeof iterator) {
  82. for (i = 0; i < len; i++) {
  83. item = source[i];
  84. returnValue = iterator.call(thisObject || source, item, i);
  85. if (returnValue === false) {
  86. break;
  87. }
  88. }
  89. }
  90. return source;
  91. };
  92. /**
  93. * 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
  94. * @namespace baidu.lang
  95. */
  96. baidu.lang = baidu.lang || {};
  97. /**
  98. * 判断目标参数是否为function或Function实例
  99. * @name baidu.lang.isFunction
  100. * @function
  101. * @grammar baidu.lang.isFunction(source)
  102. * @param {Any} source 目标参数
  103. * @version 1.2
  104. * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  105. * @meta standard
  106. * @returns {boolean} 类型判断结果
  107. */
  108. baidu.lang.isFunction = function (source) {
  109. return '[object Function]' == Object.prototype.toString.call(source);
  110. };
  111. /**
  112. * 判断目标参数是否string类型或String对象
  113. * @name baidu.lang.isString
  114. * @function
  115. * @grammar baidu.lang.isString(source)
  116. * @param {Any} source 目标参数
  117. * @shortcut isString
  118. * @meta standard
  119. * @see baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  120. *
  121. * @returns {boolean} 类型判断结果
  122. */
  123. baidu.lang.isString = function (source) {
  124. return '[object String]' == Object.prototype.toString.call(source);
  125. };
  126. baidu.isString = baidu.lang.isString;
  127. /**
  128. * 判断浏览器类型和特性的属性
  129. * @namespace baidu.browser
  130. */
  131. baidu.browser = baidu.browser || {};
  132. /**
  133. * 判断是否为opera浏览器
  134. * @property opera opera版本号
  135. * @grammar baidu.browser.opera
  136. * @meta standard
  137. * @see baidu.browser.ie,baidu.browser.firefox,baidu.browser.safari,baidu.browser.chrome
  138. * @returns {Number} opera版本号
  139. */
  140. /**
  141. * opera 从10开始不是用opera后面的字符串进行版本的判断
  142. * 在Browser identification最后添加Version + 数字进行版本标识
  143. * opera后面的数字保持在9.80不变
  144. */
  145. baidu.browser.opera = /opera(\/| )(\d+(\.\d+)?)(.+?(version\/(\d+(\.\d+)?)))?/i.test(navigator.userAgent) ? + ( RegExp["\x246"] || RegExp["\x242"] ) : undefined;
  146. /**
  147. * 在目标元素的指定位置插入HTML代码
  148. * @name baidu.dom.insertHTML
  149. * @function
  150. * @grammar baidu.dom.insertHTML(element, position, html)
  151. * @param {HTMLElement|string} element 目标元素或目标元素的id
  152. * @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd
  153. * @param {string} html 要插入的html
  154. * @remark
  155. *
  156. * 对于position参数,大小写不敏感<br>
  157. * 参数的意思:beforeBegin&lt;span&gt;afterBegin this is span! beforeEnd&lt;/span&gt; afterEnd <br />
  158. * 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。
  159. *
  160. * @shortcut insertHTML
  161. * @meta standard
  162. *
  163. * @returns {HTMLElement} 目标元素
  164. */
  165. baidu.dom.insertHTML = function (element, position, html) {
  166. element = baidu.dom.g(element);
  167. var range,begin;
  168. if (element.insertAdjacentHTML && !baidu.browser.opera) {
  169. element.insertAdjacentHTML(position, html);
  170. } else {
  171. range = element.ownerDocument.createRange();
  172. position = position.toUpperCase();
  173. if (position == 'AFTERBEGIN' || position == 'BEFOREEND') {
  174. range.selectNodeContents(element);
  175. range.collapse(position == 'AFTERBEGIN');
  176. } else {
  177. begin = position == 'BEFOREBEGIN';
  178. range[begin ? 'setStartBefore' : 'setEndAfter'](element);
  179. range.collapse(begin);
  180. }
  181. range.insertNode(range.createContextualFragment(html));
  182. }
  183. return element;
  184. };
  185. baidu.insertHTML = baidu.dom.insertHTML;
  186. /**
  187. * 操作flash对象的方法,包括创建flash对象、获取flash对象以及判断flash插件的版本号
  188. * @namespace baidu.swf
  189. */
  190. baidu.swf = baidu.swf || {};
  191. /**
  192. * 浏览器支持的flash插件版本
  193. * @property version 浏览器支持的flash插件版本
  194. * @grammar baidu.swf.version
  195. * @return {String} 版本号
  196. * @meta standard
  197. */
  198. baidu.swf.version = (function () {
  199. var n = navigator;
  200. if (n.plugins && n.mimeTypes.length) {
  201. var plugin = n.plugins["Shockwave Flash"];
  202. if (plugin && plugin.description) {
  203. return plugin.description
  204. .replace(/([a-zA-Z]|\s)+/, "")
  205. .replace(/(\s)+r/, ".") + ".0";
  206. }
  207. } else if (window.ActiveXObject && !window.opera) {
  208. for (var i = 12; i >= 2; i--) {
  209. try {
  210. var c = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.' + i);
  211. if (c) {
  212. var version = c.GetVariable("$version");
  213. return version.replace(/WIN/g,'').replace(/,/g,'.');
  214. }
  215. } catch(e) {}
  216. }
  217. }
  218. })();
  219. /**
  220. * 操作字符串的方法
  221. * @namespace baidu.string
  222. */
  223. baidu.string = baidu.string || {};
  224. /**
  225. * 对目标字符串进行html编码
  226. * @name baidu.string.encodeHTML
  227. * @function
  228. * @grammar baidu.string.encodeHTML(source)
  229. * @param {string} source 目标字符串
  230. * @remark
  231. * 编码字符有5个:&<>"'
  232. * @shortcut encodeHTML
  233. * @meta standard
  234. * @see baidu.string.decodeHTML
  235. *
  236. * @returns {string} html编码后的字符串
  237. */
  238. baidu.string.encodeHTML = function (source) {
  239. return String(source)
  240. .replace(/&/g,'&amp;')
  241. .replace(/</g,'&lt;')
  242. .replace(/>/g,'&gt;')
  243. .replace(/"/g, "&quot;")
  244. .replace(/'/g, "&#39;");
  245. };
  246. baidu.encodeHTML = baidu.string.encodeHTML;
  247. /**
  248. * 创建flash对象的html字符串
  249. * @name baidu.swf.createHTML
  250. * @function
  251. * @grammar baidu.swf.createHTML(options)
  252. *
  253. * @param {Object} options 创建flash的选项参数
  254. * @param {string} options.id 要创建的flash的标识
  255. * @param {string} options.url flash文件的url
  256. * @param {String} options.errorMessage 未安装flash player或flash player版本号过低时的提示
  257. * @param {string} options.ver 最低需要的flash player版本号
  258. * @param {string} options.width flash的宽度
  259. * @param {string} options.height flash的高度
  260. * @param {string} options.align flash的对齐方式,允许值:middle/left/right/top/bottom
  261. * @param {string} options.base 设置用于解析swf文件中的所有相对路径语句的基本目录或URL
  262. * @param {string} options.bgcolor swf文件的背景色
  263. * @param {string} options.salign 设置缩放的swf文件在由width和height设置定义的区域内的位置。允许值:l/r/t/b/tl/tr/bl/br
  264. * @param {boolean} options.menu 是否显示右键菜单,允许值:true/false
  265. * @param {boolean} options.loop 播放到最后一帧时是否重新播放,允许值: true/false
  266. * @param {boolean} options.play flash是否在浏览器加载时就开始播放。允许值:true/false
  267. * @param {string} options.quality 设置flash播放的画质,允许值:low/medium/high/autolow/autohigh/best
  268. * @param {string} options.scale 设置flash内容如何缩放来适应设置的宽高。允许值:showall/noborder/exactfit
  269. * @param {string} options.wmode 设置flash的显示模式。允许值:window/opaque/transparent
  270. * @param {string} options.allowscriptaccess 设置flash与页面的通信权限。允许值:always/never/sameDomain
  271. * @param {string} options.allownetworking 设置swf文件中允许使用的网络API。允许值:all/internal/none
  272. * @param {boolean} options.allowfullscreen 是否允许flash全屏。允许值:true/false
  273. * @param {boolean} options.seamlesstabbing 允许设置执行无缝跳格,从而使用户能跳出flash应用程序。该参数只能在安装Flash7及更高版本的Windows中使用。允许值:true/false
  274. * @param {boolean} options.devicefont 设置静态文本对象是否以设备字体呈现。允许值:true/false
  275. * @param {boolean} options.swliveconnect 第一次加载flash时浏览器是否应启动Java。允许值:true/false
  276. * @param {Object} options.vars 要传递给flash的参数,支持JSON或string类型。
  277. *
  278. * @see baidu.swf.create
  279. * @meta standard
  280. * @returns {string} flash对象的html字符串
  281. */
  282. baidu.swf.createHTML = function (options) {
  283. options = options || {};
  284. var version = baidu.swf.version,
  285. needVersion = options['ver'] || '6.0.0',
  286. vUnit1, vUnit2, i, k, len, item, tmpOpt = {},
  287. encodeHTML = baidu.string.encodeHTML;
  288. for (k in options) {
  289. tmpOpt[k] = options[k];
  290. }
  291. options = tmpOpt;
  292. /*
  293. if (version) {
  294. version = version.split('.');
  295. needVersion = needVersion.split('.');
  296. for (i = 0; i < 3; i++) {
  297. vUnit1 = parseInt(version[i], 10);
  298. vUnit2 = parseInt(needVersion[i], 10);
  299. if (vUnit2 < vUnit1) {
  300. break;
  301. } else if (vUnit2 > vUnit1) {
  302. return '';
  303. }
  304. }
  305. } else {
  306. return '';
  307. }
  308. */
  309. var vars = options['vars'],
  310. objProperties = ['classid', 'codebase', 'id', 'width', 'height', 'align'];
  311. options['align'] = options['align'] || 'middle';
  312. options['classid'] = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000';
  313. options['codebase'] = 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0';
  314. options['movie'] = options['url'] || '';
  315. delete options['vars'];
  316. delete options['url'];
  317. if ('string' == typeof vars) {
  318. options['flashvars'] = vars;
  319. } else {
  320. var fvars = [];
  321. for (k in vars) {
  322. item = vars[k];
  323. fvars.push(k + "=" + encodeURIComponent(item));
  324. }
  325. options['flashvars'] = fvars.join('&');
  326. }
  327. var str = ['<object '];
  328. for (i = 0, len = objProperties.length; i < len; i++) {
  329. item = objProperties[i];
  330. str.push(' ', item, '="', encodeHTML(options[item]), '"');
  331. }
  332. str.push('>');
  333. var params = {
  334. 'wmode' : 1,
  335. 'scale' : 1,
  336. 'quality' : 1,
  337. 'play' : 1,
  338. 'loop' : 1,
  339. 'menu' : 1,
  340. 'salign' : 1,
  341. 'bgcolor' : 1,
  342. 'base' : 1,
  343. 'allowscriptaccess' : 1,
  344. 'allownetworking' : 1,
  345. 'allowfullscreen' : 1,
  346. 'seamlesstabbing' : 1,
  347. 'devicefont' : 1,
  348. 'swliveconnect' : 1,
  349. 'flashvars' : 1,
  350. 'movie' : 1
  351. };
  352. for (k in options) {
  353. item = options[k];
  354. k = k.toLowerCase();
  355. if (params[k] && (item || item === false || item === 0)) {
  356. str.push('<param name="' + k + '" value="' + encodeHTML(item) + '" />');
  357. }
  358. }
  359. options['src'] = options['movie'];
  360. options['name'] = options['id'];
  361. delete options['id'];
  362. delete options['movie'];
  363. delete options['classid'];
  364. delete options['codebase'];
  365. options['type'] = 'application/x-shockwave-flash';
  366. options['pluginspage'] = 'http://www.macromedia.com/go/getflashplayer';
  367. str.push('<embed');
  368. var salign;
  369. for (k in options) {
  370. item = options[k];
  371. if (item || item === false || item === 0) {
  372. if ((new RegExp("^salign\x24", "i")).test(k)) {
  373. salign = item;
  374. continue;
  375. }
  376. str.push(' ', k, '="', encodeHTML(item), '"');
  377. }
  378. }
  379. if (salign) {
  380. str.push(' salign="', encodeHTML(salign), '"');
  381. }
  382. str.push('></embed></object>');
  383. return str.join('');
  384. };
  385. /**
  386. * 在页面中创建一个flash对象
  387. * @name baidu.swf.create
  388. * @function
  389. * @grammar baidu.swf.create(options[, container])
  390. *
  391. * @param {Object} options 创建flash的选项参数
  392. * @param {string} options.id 要创建的flash的标识
  393. * @param {string} options.url flash文件的url
  394. * @param {String} options.errorMessage 未安装flash player或flash player版本号过低时的提示
  395. * @param {string} options.ver 最低需要的flash player版本号
  396. * @param {string} options.width flash的宽度
  397. * @param {string} options.height flash的高度
  398. * @param {string} options.align flash的对齐方式,允许值:middle/left/right/top/bottom
  399. * @param {string} options.base 设置用于解析swf文件中的所有相对路径语句的基本目录或URL
  400. * @param {string} options.bgcolor swf文件的背景色
  401. * @param {string} options.salign 设置缩放的swf文件在由width和height设置定义的区域内的位置。允许值:l/r/t/b/tl/tr/bl/br
  402. * @param {boolean} options.menu 是否显示右键菜单,允许值:true/false
  403. * @param {boolean} options.loop 播放到最后一帧时是否重新播放,允许值: true/false
  404. * @param {boolean} options.play flash是否在浏览器加载时就开始播放。允许值:true/false
  405. * @param {string} options.quality 设置flash播放的画质,允许值:low/medium/high/autolow/autohigh/best
  406. * @param {string} options.scale 设置flash内容如何缩放来适应设置的宽高。允许值:showall/noborder/exactfit
  407. * @param {string} options.wmode 设置flash的显示模式。允许值:window/opaque/transparent
  408. * @param {string} options.allowscriptaccess 设置flash与页面的通信权限。允许值:always/never/sameDomain
  409. * @param {string} options.allownetworking 设置swf文件中允许使用的网络API。允许值:all/internal/none
  410. * @param {boolean} options.allowfullscreen 是否允许flash全屏。允许值:true/false
  411. * @param {boolean} options.seamlesstabbing 允许设置执行无缝跳格,从而使用户能跳出flash应用程序。该参数只能在安装Flash7及更高版本的Windows中使用。允许值:true/false
  412. * @param {boolean} options.devicefont 设置静态文本对象是否以设备字体呈现。允许值:true/false
  413. * @param {boolean} options.swliveconnect 第一次加载flash时浏览器是否应启动Java。允许值:true/false
  414. * @param {Object} options.vars 要传递给flash的参数,支持JSON或string类型。
  415. *
  416. * @param {HTMLElement|string} [container] flash对象的父容器元素,不传递该参数时在当前代码位置创建flash对象。
  417. * @meta standard
  418. * @see baidu.swf.createHTML,baidu.swf.getMovie
  419. */
  420. baidu.swf.create = function (options, target) {
  421. options = options || {};
  422. var html = baidu.swf.createHTML(options)
  423. || options['errorMessage']
  424. || '';
  425. if (target && 'string' == typeof target) {
  426. target = document.getElementById(target);
  427. }
  428. baidu.dom.insertHTML( target || document.body ,'beforeEnd',html );
  429. };
  430. /**
  431. * 判断是否为ie浏览器
  432. * @name baidu.browser.ie
  433. * @field
  434. * @grammar baidu.browser.ie
  435. * @returns {Number} IE版本号
  436. */
  437. baidu.browser.ie = baidu.ie = /msie (\d+\.\d+)/i.test(navigator.userAgent) ? (document.documentMode || + RegExp['\x241']) : undefined;
  438. /**
  439. * 移除数组中的项
  440. * @name baidu.array.remove
  441. * @function
  442. * @grammar baidu.array.remove(source, match)
  443. * @param {Array} source 需要移除项的数组
  444. * @param {Any} match 要移除的项
  445. * @meta standard
  446. * @see baidu.array.removeAt
  447. *
  448. * @returns {Array} 移除后的数组
  449. */
  450. baidu.array.remove = function (source, match) {
  451. var len = source.length;
  452. while (len--) {
  453. if (len in source && source[len] === match) {
  454. source.splice(len, 1);
  455. }
  456. }
  457. return source;
  458. };
  459. /**
  460. * 判断目标参数是否Array对象
  461. * @name baidu.lang.isArray
  462. * @function
  463. * @grammar baidu.lang.isArray(source)
  464. * @param {Any} source 目标参数
  465. * @meta standard
  466. * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
  467. *
  468. * @returns {boolean} 类型判断结果
  469. */
  470. baidu.lang.isArray = function (source) {
  471. return '[object Array]' == Object.prototype.toString.call(source);
  472. };
  473. /**
  474. * 将一个变量转换成array
  475. * @name baidu.lang.toArray
  476. * @function
  477. * @grammar baidu.lang.toArray(source)
  478. * @param {mix} source 需要转换成array的变量
  479. * @version 1.3
  480. * @meta standard
  481. * @returns {array} 转换后的array
  482. */
  483. baidu.lang.toArray = function (source) {
  484. if (source === null || source === undefined)
  485. return [];
  486. if (baidu.lang.isArray(source))
  487. return source;
  488. if (typeof source.length !== 'number' || typeof source === 'string' || baidu.lang.isFunction(source)) {
  489. return [source];
  490. }
  491. if (source.item) {
  492. var l = source.length, array = new Array(l);
  493. while (l--)
  494. array[l] = source[l];
  495. return array;
  496. }
  497. return [].slice.call(source);
  498. };
  499. /**
  500. * 获得flash对象的实例
  501. * @name baidu.swf.getMovie
  502. * @function
  503. * @grammar baidu.swf.getMovie(name)
  504. * @param {string} name flash对象的名称
  505. * @see baidu.swf.create
  506. * @meta standard
  507. * @returns {HTMLElement} flash对象的实例
  508. */
  509. baidu.swf.getMovie = function (name) {
  510. var movie = document[name], ret;
  511. return baidu.browser.ie == 9 ?
  512. movie && movie.length ?
  513. (ret = baidu.array.remove(baidu.lang.toArray(movie),function(item){
  514. return item.tagName.toLowerCase() != "embed";
  515. })).length == 1 ? ret[0] : ret
  516. : movie
  517. : movie || window[name];
  518. };
  519. baidu.flash._Base = (function(){
  520. var prefix = 'bd__flash__';
  521. /**
  522. * 创建一个随机的字符串
  523. * @private
  524. * @return {String}
  525. */
  526. function _createString(){
  527. return prefix + Math.floor(Math.random() * 2147483648).toString(36);
  528. };
  529. /**
  530. * 检查flash状态
  531. * @private
  532. * @param {Object} target flash对象
  533. * @return {Boolean}
  534. */
  535. function _checkReady(target){
  536. if(typeof target !== 'undefined' && typeof target.flashInit !== 'undefined' && target.flashInit()){
  537. return true;
  538. }else{
  539. return false;
  540. }
  541. };
  542. /**
  543. * 调用之前进行压栈的函数
  544. * @private
  545. * @param {Array} callQueue 调用队列
  546. * @param {Object} target flash对象
  547. * @return {Null}
  548. */
  549. function _callFn(callQueue, target){
  550. var result = null;
  551. callQueue = callQueue.reverse();
  552. baidu.each(callQueue, function(item){
  553. result = target.call(item.fnName, item.params);
  554. item.callBack(result);
  555. });
  556. };
  557. /**
  558. * 为传入的匿名函数创建函数名
  559. * @private
  560. * @param {String|Function} fun 传入的匿名函数或者函数名
  561. * @return {String}
  562. */
  563. function _createFunName(fun){
  564. var name = '';
  565. if(baidu.lang.isFunction(fun)){
  566. name = _createString();
  567. window[name] = function(){
  568. fun.apply(window, arguments);
  569. };
  570. return name;
  571. }else if(baidu.lang.isString){
  572. return fun;
  573. }
  574. };
  575. /**
  576. * 绘制flash
  577. * @private
  578. * @param {Object} options 创建参数
  579. * @return {Object}
  580. */
  581. function _render(options){
  582. if(!options.id){
  583. options.id = _createString();
  584. }
  585. var container = options.container || '';
  586. delete(options.container);
  587. baidu.swf.create(options, container);
  588. return baidu.swf.getMovie(options.id);
  589. };
  590. return function(options, callBack){
  591. var me = this,
  592. autoRender = (typeof options.autoRender !== 'undefined' ? options.autoRender : true),
  593. createOptions = options.createOptions || {},
  594. target = null,
  595. isReady = false,
  596. callQueue = [],
  597. timeHandle = null,
  598. callBack = callBack || [];
  599. /**
  600. * 将flash文件绘制到页面上
  601. * @public
  602. * @return {Null}
  603. */
  604. me.render = function(){
  605. target = _render(createOptions);
  606. if(callBack.length > 0){
  607. baidu.each(callBack, function(funName, index){
  608. callBack[index] = _createFunName(options[funName] || new Function());
  609. });
  610. }
  611. me.call('setJSFuncName', [callBack]);
  612. };
  613. /**
  614. * 返回flash状态
  615. * @return {Boolean}
  616. */
  617. me.isReady = function(){
  618. return isReady;
  619. };
  620. /**
  621. * 调用flash接口的统一入口
  622. * @param {String} fnName 调用的函数名
  623. * @param {Array} params 传入的参数组成的数组,若不许要参数,需传入空数组
  624. * @param {Function} [callBack] 异步调用后将返回值作为参数的调用回调函数,如无返回值,可以不传入此参数
  625. * @return {Null}
  626. */
  627. me.call = function(fnName, params, callBack){
  628. if(!fnName) return null;
  629. callBack = callBack || new Function();
  630. var result = null;
  631. if(isReady){
  632. result = target.call(fnName, params);
  633. callBack(result);
  634. }else{
  635. callQueue.push({
  636. fnName: fnName,
  637. params: params,
  638. callBack: callBack
  639. });
  640. (!timeHandle) && (timeHandle = setInterval(_check, 200));
  641. }
  642. };
  643. /**
  644. * 为传入的匿名函数创建函数名
  645. * @public
  646. * @param {String|Function} fun 传入的匿名函数或者函数名
  647. * @return {String}
  648. */
  649. me.createFunName = function(fun){
  650. return _createFunName(fun);
  651. };
  652. /**
  653. * 检查flash是否ready, 并进行调用
  654. * @private
  655. * @return {Null}
  656. */
  657. function _check(){
  658. if(_checkReady(target)){
  659. clearInterval(timeHandle);
  660. timeHandle = null;
  661. _call();
  662. isReady = true;
  663. }
  664. };
  665. /**
  666. * 调用之前进行压栈的函数
  667. * @private
  668. * @return {Null}
  669. */
  670. function _call(){
  671. _callFn(callQueue, target);
  672. callQueue = [];
  673. }
  674. autoRender && me.render();
  675. };
  676. })();
  677. /**
  678. * 创建flash based imageUploader
  679. * @class
  680. * @grammar baidu.flash.imageUploader(options)
  681. * @param {Object} createOptions 创建flash时需要的参数,请参照baidu.swf.create文档
  682. * @config {Object} vars 创建imageUploader时所需要的参数
  683. * @config {Number} vars.gridWidth 每一个预览图片所占的宽度,应该为flash寛的整除
  684. * @config {Number} vars.gridHeight 每一个预览图片所占的高度,应该为flash高的整除
  685. * @config {Number} vars.picWidth 单张预览图片的宽度
  686. * @config {Number} vars.picHeight 单张预览图片的高度
  687. * @config {String} vars.uploadDataFieldName POST请求中图片数据的key,默认值'picdata'
  688. * @config {String} vars.picDescFieldName POST请求中图片描述的key,默认值'picDesc'
  689. * @config {Number} vars.maxSize 文件的最大体积,单位'MB'
  690. * @config {Number} vars.compressSize 上传前如果图片体积超过该值,会先压缩
  691. * @config {Number} vars.maxNum:32 最大上传多少个文件
  692. * @config {Number} vars.compressLength 能接受的最大边长,超过该值会等比压缩
  693. * @config {String} vars.url 上传的url地址
  694. * @config {Number} vars.mode mode == 0时,是使用滚动条,mode == 1时,拉伸flash, 默认值为0
  695. * @see baidu.swf.createHTML
  696. * @param {String} backgroundUrl 背景图片路径
  697. * @param {String} listBacgroundkUrl 布局控件背景
  698. * @param {String} buttonUrl 按钮图片不背景
  699. * @param {String|Function} selectFileCallback 选择文件的回调
  700. * @param {String|Function} exceedFileCallback文件超出限制的最大体积时的回调
  701. * @param {String|Function} deleteFileCallback 删除文件的回调
  702. * @param {String|Function} startUploadCallback 开始上传某个文件时的回调
  703. * @param {String|Function} uploadCompleteCallback 某个文件上传完成的回调
  704. * @param {String|Function} uploadErrorCallback 某个文件上传失败的回调
  705. * @param {String|Function} allCompleteCallback 全部上传完成时的回调
  706. * @param {String|Function} changeFlashHeight 改变Flash的高度,mode==1的时候才有用
  707. */
  708. baidu.flash.imageUploader = baidu.flash.imageUploader || function(options){
  709. var me = this,
  710. options = options || {},
  711. _flash = new baidu.flash._Base(options, [
  712. 'selectFileCallback',
  713. 'exceedFileCallback',
  714. 'deleteFileCallback',
  715. 'startUploadCallback',
  716. 'uploadCompleteCallback',
  717. 'uploadErrorCallback',
  718. 'allCompleteCallback',
  719. 'changeFlashHeight'
  720. ]);
  721. /**
  722. * 开始或回复上传图片
  723. * @public
  724. * @return {Null}
  725. */
  726. me.upload = function(){
  727. _flash.call('upload');
  728. };
  729. /**
  730. * 暂停上传图片
  731. * @public
  732. * @return {Null}
  733. */
  734. me.pause = function(){
  735. _flash.call('pause');
  736. };
  737. me.addCustomizedParams = function(index,obj){
  738. _flash.call('addCustomizedParams',[index,obj]);
  739. }
  740. };
  741. /**
  742. * 操作原生对象的方法
  743. * @namespace baidu.object
  744. */
  745. baidu.object = baidu.object || {};
  746. /**
  747. * 将源对象的所有属性拷贝到目标对象中
  748. * @author erik
  749. * @name baidu.object.extend
  750. * @function
  751. * @grammar baidu.object.extend(target, source)
  752. * @param {Object} target 目标对象
  753. * @param {Object} source 源对象
  754. * @see baidu.array.merge
  755. * @remark
  756. *
  757. 1.目标对象中,与源对象key相同的成员将会被覆盖。<br>
  758. 2.源对象的prototype成员不会拷贝。
  759. * @shortcut extend
  760. * @meta standard
  761. *
  762. * @returns {Object} 目标对象
  763. */
  764. baidu.extend =
  765. baidu.object.extend = function (target, source) {
  766. for (var p in source) {
  767. if (source.hasOwnProperty(p)) {
  768. target[p] = source[p];
  769. }
  770. }
  771. return target;
  772. };
  773. /**
  774. * 创建flash based fileUploader
  775. * @class
  776. * @grammar baidu.flash.fileUploader(options)
  777. * @param {Object} options
  778. * @config {Object} createOptions 创建flash时需要的参数,请参照baidu.swf.create文档
  779. * @config {String} createOptions.width
  780. * @config {String} createOptions.height
  781. * @config {Number} maxNum 最大可选文件数
  782. * @config {Function|String} selectFile
  783. * @config {Function|String} exceedMaxSize
  784. * @config {Function|String} deleteFile
  785. * @config {Function|String} uploadStart
  786. * @config {Function|String} uploadComplete
  787. * @config {Function|String} uploadError
  788. * @config {Function|String} uploadProgress
  789. */
  790. baidu.flash.fileUploader = baidu.flash.fileUploader || function(options){
  791. var me = this,
  792. options = options || {};
  793. options.createOptions = baidu.extend({
  794. wmod: 'transparent'
  795. },options.createOptions || {});
  796. var _flash = new baidu.flash._Base(options, [
  797. 'selectFile',
  798. 'exceedMaxSize',
  799. 'deleteFile',
  800. 'uploadStart',
  801. 'uploadComplete',
  802. 'uploadError',
  803. 'uploadProgress'
  804. ]);
  805. _flash.call('setMaxNum', options.maxNum ? [options.maxNum] : [1]);
  806. /**
  807. * 设置当鼠标移动到flash上时,是否变成手型
  808. * @public
  809. * @param {Boolean} isCursor
  810. * @return {Null}
  811. */
  812. me.setHandCursor = function(isCursor){
  813. _flash.call('setHandCursor', [isCursor || false]);
  814. };
  815. /**
  816. * 设置鼠标相应函数名
  817. * @param {String|Function} fun
  818. */
  819. me.setMSFunName = function(fun){
  820. _flash.call('setMSFunName',[_flash.createFunName(fun)]);
  821. };
  822. /**
  823. * 执行上传操作
  824. * @param {String} url 上传的url
  825. * @param {String} fieldName 上传的表单字段名
  826. * @param {Object} postData 键值对,上传的POST数据
  827. * @param {Number|Array|null|-1} [index]上传的文件序列
  828. * Int值上传该文件
  829. * Array一次串行上传该序列文件
  830. * -1/null上传所有文件
  831. * @return {Null}
  832. */
  833. me.upload = function(url, fieldName, postData, index){
  834. if(typeof url !== 'string' || typeof fieldName !== 'string') return null;
  835. if(typeof index === 'undefined') index = -1;
  836. _flash.call('upload', [url, fieldName, postData, index]);
  837. };
  838. /**
  839. * 取消上传操作
  840. * @public
  841. * @param {Number|-1} index
  842. */
  843. me.cancel = function(index){
  844. if(typeof index === 'undefined') index = -1;
  845. _flash.call('cancel', [index]);
  846. };
  847. /**
  848. * 删除文件
  849. * @public
  850. * @param {Number|Array} [index] 要删除的index,不传则全部删除
  851. * @param {Function} callBack
  852. * @param
  853. * */
  854. me.deleteFile = function(index, callBack){
  855. var callBackAll = function(list){
  856. callBack && callBack(list);
  857. };
  858. if(typeof index === 'undefined'){
  859. _flash.call('deleteFilesAll', [], callBackAll);
  860. return;
  861. };
  862. if(typeof index === 'Number') index = [index];
  863. index.sort(function(a,b){
  864. return b-a;
  865. });
  866. baidu.each(index, function(item){
  867. _flash.call('deleteFileBy', item, callBackAll);
  868. });
  869. };
  870. /**
  871. * 添加文件类型,支持macType
  872. * @public
  873. * @param {Object|Array[Object]} type {description:String, extention:String}
  874. * @return {Null};
  875. */
  876. me.addFileType = function(type){
  877. var type = type || [[]];
  878. if(type instanceof Array) type = [type];
  879. else type = [[type]];
  880. _flash.call('addFileTypes', type);
  881. };
  882. /**
  883. * 设置文件类型,支持macType
  884. * @public
  885. * @param {Object|Array[Object]} type {description:String, extention:String}
  886. * @return {Null};
  887. */
  888. me.setFileType = function(type){
  889. var type = type || [[]];
  890. if(type instanceof Array) type = [type];
  891. else type = [[type]];
  892. _flash.call('setFileTypes', type);
  893. };
  894. /**
  895. * 设置可选文件的数量限制
  896. * @public
  897. * @param {Number} num
  898. * @return {Null}
  899. */
  900. me.setMaxNum = function(num){
  901. _flash.call('setMaxNum', [num]);
  902. };
  903. /**
  904. * 设置可选文件大小限制,以兆M为单位
  905. * @public
  906. * @param {Number} num,0为无限制
  907. * @return {Null}
  908. */
  909. me.setMaxSize = function(num){
  910. _flash.call('setMaxSize', [num]);
  911. };
  912. /**
  913. * @public
  914. */
  915. me.getFileAll = function(callBack){
  916. _flash.call('getFileAll', [], callBack);
  917. };
  918. /**
  919. * @public
  920. * @param {Number} index
  921. * @param {Function} [callBack]
  922. */
  923. me.getFileByIndex = function(index, callBack){
  924. _flash.call('getFileByIndex', [], callBack);
  925. };
  926. /**
  927. * @public
  928. * @param {Number} index
  929. * @param {function} [callBack]
  930. */
  931. me.getStatusByIndex = function(index, callBack){
  932. _flash.call('getStatusByIndex', [], callBack);
  933. };
  934. };
  935. /**
  936. * 使用动态script标签请求服务器资源,包括由服务器端的回调和浏览器端的回调
  937. * @namespace baidu.sio
  938. */
  939. baidu.sio = baidu.sio || {};
  940. /**
  941. *
  942. * @param {HTMLElement} src script节点
  943. * @param {String} url script节点的地址
  944. * @param {String} [charset] 编码
  945. */
  946. baidu.sio._createScriptTag = function(scr, url, charset){
  947. scr.setAttribute('type', 'text/javascript');
  948. charset && scr.setAttribute('charset', charset);
  949. scr.setAttribute('src', url);
  950. document.getElementsByTagName('head')[0].appendChild(scr);
  951. };
  952. /**
  953. * 删除script的属性,再删除script标签,以解决修复内存泄漏的问题
  954. *
  955. * @param {HTMLElement} src script节点
  956. */
  957. baidu.sio._removeScriptTag = function(scr){
  958. if (scr.clearAttributes) {
  959. scr.clearAttributes();
  960. } else {
  961. for (var attr in scr) {
  962. if (scr.hasOwnProperty(attr)) {
  963. delete scr[attr];
  964. }
  965. }
  966. }
  967. if(scr && scr.parentNode){
  968. scr.parentNode.removeChild(scr);
  969. }
  970. scr = null;
  971. };
  972. /**
  973. * 通过script标签加载数据,加载完成由浏览器端触发回调
  974. * @name baidu.sio.callByBrowser
  975. * @function
  976. * @grammar baidu.sio.callByBrowser(url, opt_callback, opt_options)
  977. * @param {string} url 加载数据的url
  978. * @param {Function|string} opt_callback 数据加载结束时调用的函数或函数名
  979. * @param {Object} opt_options 其他可选项
  980. * @config {String} [charset] script的字符集
  981. * @config {Integer} [timeOut] 超时时间,超过这个时间将不再响应本请求,并触发onfailure函数
  982. * @config {Function} [onfailure] timeOut设定后才生效,到达超时时间时触发本函数
  983. * @remark
  984. * 1、与callByServer不同,callback参数只支持Function类型,不支持string。
  985. * 2、如果请求了一个不存在的页面,callback函数在IE/opera下也会被调用,因此使用者需要在onsuccess函数中判断数据是否正确加载。
  986. * @meta standard
  987. * @see baidu.sio.callByServer
  988. */
  989. baidu.sio.callByBrowser = function (url, opt_callback, opt_options) {
  990. var scr = document.createElement("SCRIPT"),
  991. scriptLoaded = 0,
  992. options = opt_options || {},
  993. charset = options['charset'],
  994. callback = opt_callback || function(){},
  995. timeOut = options['timeOut'] || 0,
  996. timer;
  997. scr.onload = scr.onreadystatechange = function () {
  998. if (scriptLoaded) {
  999. return;
  1000. }
  1001. var readyState = scr.readyState;
  1002. if ('undefined' == typeof readyState
  1003. || readyState == "loaded"
  1004. || readyState == "complete") {
  1005. scriptLoaded = 1;
  1006. try {
  1007. callback();
  1008. clearTimeout(timer);
  1009. } finally {
  1010. scr.onload = scr.onreadystatechange = null;
  1011. baidu.sio._removeScriptTag(scr);
  1012. }
  1013. }
  1014. };
  1015. if( timeOut ){
  1016. timer = setTimeout(function(){
  1017. scr.onload = scr.onreadystatechange = null;
  1018. baidu.sio._removeScriptTag(scr);
  1019. options.onfailure && options.onfailure();
  1020. }, timeOut);
  1021. }
  1022. baidu.sio._createScriptTag(scr, url, charset);
  1023. };
  1024. /**
  1025. * 通过script标签加载数据,加载完成由服务器端触发回调
  1026. * @name baidu.sio.callByServer
  1027. * @function
  1028. * @grammar baidu.sio.callByServer(url, callback[, opt_options])
  1029. * @param {string} url 加载数据的url.
  1030. * @param {Function|string} callback 服务器端调用的函数或函数名。如果没有指定本参数,将在URL中寻找options['queryField']做为callback的方法名.
  1031. * @param {Object} opt_options 加载数据时的选项.
  1032. * @config {string} [charset] script的字符集
  1033. * @config {string} [queryField] 服务器端callback请求字段名,默认为callback
  1034. * @config {Integer} [timeOut] 超时时间(单位:ms),超过这个时间将不再响应本请求,并触发onfailure函数
  1035. * @config {Function} [onfailure] timeOut设定后才生效,到达超时时间时触发本函数
  1036. * @remark
  1037. * 如果url中已经包含key为“options['queryField']”的query项,将会被替换成callback中参数传递或自动生成的函数名。
  1038. * @meta standard
  1039. * @see baidu.sio.callByBrowser
  1040. */
  1041. baidu.sio.callByServer = /**@function*/function(url, callback, opt_options) {
  1042. var scr = document.createElement('SCRIPT'),
  1043. prefix = 'bd__cbs__',
  1044. callbackName,
  1045. callbackImpl,
  1046. options = opt_options || {},
  1047. charset = options['charset'],
  1048. queryField = options['queryField'] || 'callback',
  1049. timeOut = options['timeOut'] || 0,
  1050. timer,
  1051. reg = new RegExp('(\\?|&)' + queryField + '=([^&]*)'),
  1052. matches;
  1053. if (baidu.lang.isFunction(callback)) {
  1054. callbackName = prefix + Math.floor(Math.random() * 2147483648).toString(36);
  1055. window[callbackName] = getCallBack(0);
  1056. } else if(baidu.lang.isString(callback)){
  1057. callbackName = callback;
  1058. } else {
  1059. if (matches = reg.exec(url)) {
  1060. callbackName = matches[2];
  1061. }
  1062. }
  1063. if( timeOut ){
  1064. timer = setTimeout(getCallBack(1), timeOut);
  1065. }
  1066. url = url.replace(reg, '\x241' + queryField + '=' + callbackName);
  1067. if (url.search(reg) < 0) {
  1068. url += (url.indexOf('?') < 0 ? '?' : '&') + queryField + '=' + callbackName;
  1069. }
  1070. baidu.sio._createScriptTag(scr, url, charset);
  1071. /*
  1072. * 返回一个函数,用于立即(挂在window上)或者超时(挂在setTimeout中)时执行
  1073. */
  1074. function getCallBack(onTimeOut){
  1075. /*global callbackName, callback, scr, options;*/
  1076. return function(){
  1077. try {
  1078. if( onTimeOut ){
  1079. options.onfailure && options.onfailure();
  1080. }else{
  1081. callback.apply(window, arguments);
  1082. clearTimeout(timer);
  1083. }
  1084. window[callbackName] = null;
  1085. delete window[callbackName];
  1086. } catch (exception) {
  1087. } finally {
  1088. baidu.sio._removeScriptTag(scr);
  1089. }
  1090. }
  1091. }
  1092. };
  1093. /**
  1094. * 通过请求一个图片的方式令服务器存储一条日志
  1095. * @function
  1096. * @grammar baidu.sio.log(url)
  1097. * @param {string} url 要发送的地址.
  1098. * @author: int08h,leeight
  1099. */
  1100. baidu.sio.log = function(url) {
  1101. var img = new Image(),
  1102. key = 'tangram_sio_log_' + Math.floor(Math.random() *
  1103. 2147483648).toString(36);
  1104. window[key] = img;
  1105. img.onload = img.onerror = img.onabort = function() {
  1106. img.onload = img.onerror = img.onabort = null;
  1107. window[key] = null;
  1108. img = null;
  1109. };
  1110. img.src = url;
  1111. };