Flash.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. define("dojox/embed/Flash", ["dojo"], function(dojo) {
  2. /*******************************************************
  3. dojox.embed.Flash
  4. Base functionality to insert a flash movie into
  5. a document on the fly.
  6. Usage:
  7. var movie=new dojox.embed.Flash({ args }, containerNode);
  8. ******************************************************/
  9. dojo.getObject("embed", true, dojox);
  10. function htmlEscape(str) {
  11. return String(str)
  12. .replace(/&/g, '&')
  13. .replace(/</g, '&lt;')
  14. .replace(/"/g, '&quot;')
  15. .replace(/'/g, '&apos;');
  16. }
  17. var fMarkup, fVersion;
  18. var minimumVersion = 9; // anything below this will throw an error (may overwrite)
  19. var keyBase = "dojox-embed-flash-", keyCount=0;
  20. var _baseKwArgs = {
  21. expressInstall: false,
  22. width: 320,
  23. height: 240,
  24. swLiveConnect: "true",
  25. allowScriptAccess: "sameDomain",
  26. allowNetworking:"all",
  27. style: null,
  28. redirect: null
  29. };
  30. function prep(kwArgs){
  31. kwArgs = dojo.delegate(_baseKwArgs, kwArgs);
  32. if(!("path" in kwArgs)){
  33. console.error("dojox.embed.Flash(ctor):: no path reference to a Flash movie was provided.");
  34. return null;
  35. }
  36. if(!("id" in kwArgs)){
  37. kwArgs.id = (keyBase + keyCount++);
  38. }
  39. return kwArgs;
  40. }
  41. if(dojo.isIE){
  42. fMarkup = function(kwArgs){
  43. kwArgs = prep(kwArgs);
  44. if(!kwArgs){ return null; }
  45. var p;
  46. var path = kwArgs.path;
  47. if(kwArgs.vars){
  48. var a = [];
  49. for(p in kwArgs.vars){
  50. a.push(encodeURIComponent(p) + '=' + encodeURIComponent(kwArgs.vars[p]));
  51. }
  52. kwArgs.params.FlashVars = a.join("&");
  53. delete kwArgs.vars;
  54. }
  55. var s = '<object id="' + htmlEscape(String(kwArgs.id)) + '" '
  56. + 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
  57. + 'width="' + htmlEscape(String(kwArgs.width)) + '" '
  58. + 'height="' + htmlEscape(String(kwArgs.height)) + '"'
  59. + ((kwArgs.style)?' style="' + htmlEscape(String(kwArgs.style)) + '"':'')
  60. + '>'
  61. + '<param name="movie" value="' + htmlEscape(String(path)) + '" />';
  62. if(kwArgs.params){
  63. for(p in kwArgs.params){
  64. s += '<param name="' + htmlEscape(p) + '" value="' + htmlEscape(String(kwArgs.params[p])) + '" />';
  65. }
  66. }
  67. s += '</object>';
  68. return { id: kwArgs.id, markup: s };
  69. };
  70. fVersion = (function(){
  71. var testVersion = 10, testObj = null;
  72. while(!testObj && testVersion > 7){
  73. try {
  74. testObj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + testVersion--);
  75. }catch(e){ }
  76. }
  77. if(testObj){
  78. var v = testObj.GetVariable("$version").split(" ")[1].split(",");
  79. return {
  80. major: (v[0]!=null) ? parseInt(v[0]) : 0,
  81. minor: (v[1]!=null) ? parseInt(v[1]) : 0,
  82. rev: (v[2]!=null) ? parseInt(v[2]) : 0
  83. };
  84. }
  85. return { major: 0, minor: 0, rev: 0 };
  86. })();
  87. // attach some cleanup for IE, thanks to deconcept :)
  88. dojo.addOnUnload(function(){
  89. var dummy = function(){};
  90. var objs = dojo.query("object").
  91. reverse().
  92. style("display", "none").
  93. forEach(function(i){
  94. for(var p in i){
  95. if((p != "FlashVars") && dojo.isFunction(i[p])){
  96. try{
  97. i[p] = dummy;
  98. }catch(e){}
  99. }
  100. }
  101. });
  102. });
  103. } else {
  104. // *** Sane browsers branch ******************************************************************
  105. fMarkup = function(kwArgs){
  106. kwArgs = prep(kwArgs);
  107. if(!kwArgs){ return null; }
  108. var p;
  109. var path = kwArgs.path;
  110. if(kwArgs.vars){
  111. var a = [];
  112. for(p in kwArgs.vars){
  113. a.push(encodeURIComponent(p) + '=' + encodeURIComponent(kwArgs.vars[p]));
  114. }
  115. kwArgs.params.flashVars = a.join("&");
  116. delete kwArgs.vars;
  117. }
  118. var s = '<embed type="application/x-shockwave-flash" '
  119. + 'src="' + htmlEscape(String(path)) + '" '
  120. + 'id="' + htmlEscape(String(kwArgs.id)) + '" '
  121. + 'width="' + htmlEscape(String(kwArgs.width)) + '" '
  122. + 'height="' + htmlEscape(String(kwArgs.height)) + '"'
  123. + ((kwArgs.style)?' style="' + htmlEscape(String(kwArgs.style)) + '" ':'')
  124. + 'pluginspage="' + window.location.protocol + '//www.adobe.com/go/getflashplayer" ';
  125. if(kwArgs.params){
  126. for(p in kwArgs.params){
  127. s += ' ' + htmlEscape(p) + '="' + htmlEscape(String(kwArgs.params[p])) + '"';
  128. }
  129. }
  130. s += ' />';
  131. return { id: kwArgs.id, markup: s };
  132. };
  133. fVersion=(function(){
  134. var plugin = navigator.plugins["Shockwave Flash"];
  135. if(plugin && plugin.description){
  136. var v = plugin.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".");
  137. return {
  138. major: (v[0]!=null) ? parseInt(v[0]) : 0,
  139. minor: (v[1]!=null) ? parseInt(v[1]) : 0,
  140. rev: (v[2]!=null) ? parseInt(v[2]) : 0
  141. };
  142. }
  143. return { major: 0, minor: 0, rev: 0 };
  144. })();
  145. }
  146. /*=====
  147. dojox.embed.__flashArgs = function(path, id, width, height, style, params, vars, expressInstall, redirect){
  148. // path: String
  149. // The URL of the movie to embed.
  150. // id: String?
  151. // A unique key that will be used as the id of the created markup. If you don't
  152. // provide this, a unique key will be generated.
  153. // width: Number?
  154. // The width of the embedded movie; the default value is 320px.
  155. // height: Number?
  156. // The height of the embedded movie; the default value is 240px
  157. // minimumVersion: Number ?
  158. // The minimum targeted version of the Flash Player (defaults to 9)
  159. // style: String?
  160. // Any CSS style information (i.e. style="background-color:transparent") you want
  161. // to define on the markup.
  162. // params: Object?
  163. // A set of key/value pairs that you want to define in the resultant markup.
  164. // vars: Object?
  165. // A set of key/value pairs that the Flash movie will interpret as FlashVars.
  166. // expressInstall: Boolean?
  167. // Whether or not to include any kind of expressInstall info. Default is false.
  168. // redirect: String?
  169. // A url to redirect the browser to if the current Flash version is not supported.
  170. this.id=id;
  171. this.path=path;
  172. this.width=width;
  173. this.minimumVersion=minimumVersion;
  174. this.height=height;
  175. this.style=style;
  176. this.params=params;
  177. this.vars=vars;
  178. this.expressInstall=expressInstall;
  179. this.redirect=redirect;
  180. }
  181. =====*/
  182. // the main entry point
  183. dojox.embed.Flash = function(/*dojox.embed.__flashArgs*/ kwArgs, /*DOMNode*/ node){
  184. // summary:
  185. // Create a wrapper object around a Flash movie; this is the DojoX equivilent
  186. // to SWFObject.
  187. //
  188. // description:
  189. // Creates a wrapper object around a Flash movie. Wrapper object will
  190. // insert the movie reference in node; when the browser first starts
  191. // grabbing the movie, onReady will be fired; when the movie has finished
  192. // loading, it will fire onLoad.
  193. //
  194. // If your movie uses ExternalInterface, you should use the onLoad event
  195. // to do any kind of proxy setup (see dojox.embed.Flash.proxy); this seems
  196. // to be the only consistent time calling EI methods are stable (since the
  197. // Flash movie will shoot several methods into the window object before
  198. // EI callbacks can be used properly).
  199. //
  200. // kwArgs: dojox.embed.__flashArgs
  201. // The various arguments that will be used to help define the Flash movie.
  202. // node: DomNode
  203. // The node where the embed object will be placed
  204. //
  205. // example:
  206. // Embed a flash movie in a document using the new operator, and get a reference to it.
  207. // | var movie = new dojox.embed.Flash({
  208. // | path: "path/to/my/movie.swf",
  209. // | width: 400,
  210. // | height: 300
  211. // | }, myWrapperNode, "testLoaded");
  212. //
  213. // example:
  214. // Embed a flash movie in a document without using the new operator.
  215. // | var movie = dojox.embed.Flash({
  216. // | path: "path/to/my/movie.swf",
  217. // | width: 400,
  218. // | height: 300,
  219. // | style: "position:absolute;top:0;left:0"
  220. // | }, myWrapperNode, "testLoaded");
  221. //
  222. // File can only be run from a server, due to SWF dependency.
  223. if(location.href.toLowerCase().indexOf("file://")>-1){
  224. throw new Error("dojox.embed.Flash can't be run directly from a file. To instatiate the required SWF correctly it must be run from a server, like localHost.");
  225. }
  226. // available: Number
  227. // If there is a flash player available, and if so what version.
  228. this.available = dojox.embed.Flash.available;
  229. // minimumVersion: Number
  230. // The minimum version of Flash required to run this movie.
  231. this.minimumVersion = kwArgs.minimumVersion || minimumVersion;
  232. // id: String
  233. // The id of the DOMNode to be used for this movie. Can be used with dojo.byId to get a reference.
  234. this.id = null;
  235. // movie: FlashObject
  236. // A reference to the movie itself.
  237. this.movie = null;
  238. // domNode: DOMNode
  239. // A reference to the DOMNode that contains this movie.
  240. this.domNode = null;
  241. if(node){
  242. node = dojo.byId(node);
  243. }
  244. // setTimeout Fixes #8743 - creating double SWFs
  245. // also allows time for code to attach to onError
  246. setTimeout(dojo.hitch(this, function(){
  247. if(kwArgs.expressInstall || this.available && this.available >= this.minimumVersion){
  248. if(kwArgs && node){
  249. this.init(kwArgs, node);
  250. }else{
  251. this.onError("embed.Flash was not provided with the proper arguments.");
  252. }
  253. }else{
  254. if(!this.available){
  255. this.onError("Flash is not installed.");
  256. }else{
  257. this.onError("Flash version detected: "+this.available+" is out of date. Minimum required: "+this.minimumVersion);
  258. }
  259. }
  260. }), 100);
  261. };
  262. dojo.extend(dojox.embed.Flash, {
  263. onReady: function(/*HTMLObject*/ movie){
  264. // summary:
  265. // Stub function for you to attach to when the movie reference is first
  266. // pushed into the document.
  267. },
  268. onLoad: function(/*HTMLObject*/ movie){
  269. // summary:
  270. // Stub function for you to attach to when the movie has finished downloading
  271. // and is ready to be manipulated.
  272. },
  273. onError: function(msg){
  274. },
  275. _onload: function(){
  276. // summary:
  277. // Internal. Cleans up before calling onLoad.
  278. clearInterval(this._poller);
  279. delete this._poller;
  280. delete this._pollCount;
  281. delete this._pollMax;
  282. this.onLoad(this.movie);
  283. },
  284. init: function(/*dojox.embed.__flashArgs*/ kwArgs, /*DOMNode?*/ node){
  285. // summary
  286. // Initialize (i.e. place and load) the movie based on kwArgs.
  287. this.destroy(); // ensure we are clean first.
  288. node = dojo.byId(node || this.domNode);
  289. if(!node){ throw new Error("dojox.embed.Flash: no domNode reference has been passed."); }
  290. // vars to help determine load status
  291. var p = 0, testLoaded=false;
  292. this._poller = null; this._pollCount = 0; this._pollMax = 15; this.pollTime = 100;
  293. if(dojox.embed.Flash.initialized){
  294. this.id = dojox.embed.Flash.place(kwArgs, node);
  295. this.domNode = node;
  296. setTimeout(dojo.hitch(this, function(){
  297. this.movie = this.byId(this.id, kwArgs.doc);
  298. this.onReady(this.movie);
  299. this._poller = setInterval(dojo.hitch(this, function(){
  300. // catch errors if not quite ready.
  301. try{
  302. p = this.movie.PercentLoaded();
  303. }catch(e){
  304. console.warn("this.movie.PercentLoaded() failed", e, this.movie);
  305. }
  306. if(p == 100){
  307. // if percent = 100, movie is fully loaded and we're communicating
  308. this._onload();
  309. }else if(p==0 && this._pollCount++ > this._pollMax){
  310. // after several attempts, we're not past zero.
  311. clearInterval(this._poller);
  312. throw new Error("Building SWF failed.");
  313. }
  314. }), this.pollTime);
  315. }), 1);
  316. }
  317. },
  318. _destroy: function(){
  319. // summary
  320. // Kill the movie and reset all the properties of this object.
  321. try{
  322. this.domNode.removeChild(this.movie);
  323. }catch(e){}
  324. this.id = this.movie = this.domNode = null;
  325. },
  326. destroy: function(){
  327. // summary
  328. // Public interface for destroying all the properties in this object.
  329. // Will also clean all proxied methods.
  330. if(!this.movie){ return; }
  331. // remove any proxy functions
  332. var test = dojo.delegate({
  333. id: true,
  334. movie: true,
  335. domNode: true,
  336. onReady: true,
  337. onLoad: true
  338. });
  339. for(var p in this){
  340. if(!test[p]){
  341. delete this[p];
  342. }
  343. }
  344. // poll the movie
  345. if(this._poller){
  346. // wait until onLoad to destroy
  347. dojo.connect(this, "onLoad", this, "_destroy");
  348. } else {
  349. this._destroy();
  350. }
  351. },
  352. byId: function (movieName, doc){
  353. // summary:
  354. // Gets Flash movie by id.
  355. // description:
  356. // Probably includes methods for outdated
  357. // browsers, but this should catch all cases.
  358. // arguments:
  359. // movieName: String
  360. // The name of the SWF
  361. // doc: Object
  362. // The document, if not current window
  363. // (not fully supported)
  364. // example:
  365. // | var movie = dojox.embed.Flash.byId("myId");
  366. //
  367. doc = doc || document;
  368. if(doc.embeds[movieName]){
  369. return doc.embeds[movieName];
  370. }
  371. if(doc[movieName]){
  372. return doc[movieName];
  373. }
  374. if(window[movieName]){
  375. return window[movieName];
  376. }
  377. if(document[movieName]){
  378. return document[movieName];
  379. }
  380. return null;
  381. }
  382. });
  383. // expose information through the constructor function itself.
  384. dojo.mixin(dojox.embed.Flash, {
  385. // summary:
  386. // A singleton object used internally to get information
  387. // about the Flash player available in a browser, and
  388. // as the factory for generating and placing markup in a
  389. // document.
  390. //
  391. // minSupported: Number
  392. // The minimum supported version of the Flash Player, defaults to 8.
  393. // available: Number
  394. // Used as both a detection (i.e. if(dojox.embed.Flash.available){ })
  395. // and as a variable holding the major version of the player installed.
  396. // supported: Boolean
  397. // Whether or not the Flash Player installed is supported by dojox.embed.
  398. // version: Object
  399. // The version of the installed Flash Player; takes the form of
  400. // { major, minor, rev }. To get the major version, you'd do this:
  401. // var v=dojox.embed.Flash.version.major;
  402. // initialized: Boolean
  403. // Whether or not the Flash engine is available for use.
  404. // onInitialize: Function
  405. // A stub you can connect to if you are looking to fire code when the
  406. // engine becomes available. A note: DO NOT use this event to
  407. // place a movie in a document; it will usually fire before DOMContentLoaded
  408. // is fired, and you will get an error. Use dojo.addOnLoad instead.
  409. minSupported : 8,
  410. available: fVersion.major,
  411. supported: (fVersion.major >= fVersion.required),
  412. minimumRequired: fVersion.required,
  413. version: fVersion,
  414. initialized: false,
  415. onInitialize: function(){
  416. dojox.embed.Flash.initialized = true;
  417. },
  418. __ie_markup__: function(kwArgs){
  419. return fMarkup(kwArgs);
  420. },
  421. proxy: function(/*dojox.embed.Flash*/ obj, /*Array|String*/ methods){
  422. // summary:
  423. // Create the set of passed methods on the dojox.embed.Flash object
  424. // so that you can call that object directly, as opposed to having to
  425. // delve into the internal movie to do this. Intended to make working
  426. // with Flash movies that use ExternalInterface much easier to use.
  427. //
  428. // example:
  429. // Create "setMessage" and "getMessage" methods on foo.
  430. // | var foo = new dojox.embed.Flash(args, someNode);
  431. // | dojo.connect(foo, "onLoad", dojo.hitch(foo, function(){
  432. // | dojox.embed.Flash.proxy(this, [ "setMessage", "getMessage" ]);
  433. // | this.setMessage("dojox.embed.Flash.proxy is pretty cool...");
  434. // | console.log(this.getMessage());
  435. // | }));
  436. dojo.forEach((dojo.isArray(methods) ? methods : [ methods ]), function(item){
  437. this[item] = dojo.hitch(this, function(){
  438. return (function(){
  439. return eval(this.movie.CallFunction(
  440. '<invoke name="' + item + '" returntype="javascript">'
  441. + '<arguments>'
  442. + dojo.map(arguments, function(item){
  443. // FIXME:
  444. // investigate if __flash__toXML will
  445. // accept direct application via map()
  446. // (e.g., does it ignore args past the
  447. // first? or does it blow up?)
  448. return __flash__toXML(item);
  449. }).join("")
  450. + '</arguments>'
  451. + '</invoke>'
  452. ));
  453. }).apply(this, arguments||[]);
  454. });
  455. }, obj);
  456. }
  457. });
  458. dojox.embed.Flash.place = function(kwArgs, node){
  459. var o = fMarkup(kwArgs);
  460. node = dojo.byId(node);
  461. if(!node){
  462. node = dojo.doc.createElement("div");
  463. node.id = o.id+"-container";
  464. dojo.body().appendChild(node);
  465. }
  466. if(o){
  467. node.innerHTML = o.markup;
  468. return o.id;
  469. }
  470. return null;
  471. }
  472. dojox.embed.Flash.onInitialize();
  473. return dojox.embed.Flash;
  474. });