PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/elements/upload/resources/Main.as

https://github.com/tornak47/apf
ActionScript | 531 lines | 406 code | 107 blank | 18 comment | 74 complexity | 7879dd9a95632ad76d05b9be38ade84e MD5 | raw file
  1. /**
  2. * Swiff.Uploader
  3. *
  4. * Credits: A lot of good parts are inspired by the awesome www.swfupload.org
  5. *
  6. * @licence MIT Licence
  7. *
  8. * @author Harald Kirschner <http://digitarald.de>
  9. * @author Anders Rasmussen <aras@dr.dk>
  10. * @author Valerio Proietti, <http://mad4milk.net>
  11. * @author Mike de Boer <mike AT ajax DOT org>
  12. * @copyright Authors
  13. */
  14. package
  15. {
  16. import flash.display.Sprite;
  17. import flash.display.StageAlign;
  18. import flash.display.StageScaleMode;
  19. import flash.display.MovieClip;
  20. import flash.display.Loader;
  21. import flash.events.*;
  22. import flash.utils.*;
  23. import flash.system.Security;
  24. import flash.net.FileReference;
  25. import flash.net.FileReferenceList;
  26. import flash.net.FileFilter;
  27. import flash.net.URLRequest;
  28. import flash.external.ExternalInterface;
  29. import flash.text.AntiAliasType;
  30. import flash.text.GridFitType;
  31. import flash.text.StaticText;
  32. import flash.text.StyleSheet;
  33. import flash.text.TextDisplayMode;
  34. import flash.text.TextField;
  35. import flash.text.TextFieldType;
  36. import flash.text.TextFieldAutoSize;
  37. import flash.text.TextFormat;
  38. import Escaper;
  39. import File;
  40. public class Main extends Sprite
  41. {
  42. public var options:Object = {
  43. typeFilter: null,
  44. typeFilterDescription: null,
  45. multiple: null,
  46. queued: null,
  47. verbose: false,
  48. width: 128,
  49. height: 32,
  50. passStatus: null,
  51. url: null,
  52. method: null,
  53. data: null,
  54. mergeData: null,
  55. fieldName: null,
  56. progressGraphSize: 10,
  57. fileSizeMin: 1,
  58. fileSizeMax: null,// Official 100 MB limit for FileReference
  59. allowDuplicates: false,
  60. timeLimit: null,
  61. policyFile: null,
  62. buttonImage: null
  63. };
  64. public var fileList:Array = new Array();
  65. public var uploading:uint = 0;
  66. public var size:uint = 0;
  67. public var bytesLoaded:uint = 0;
  68. public var rate:uint = 0;
  69. public var playerID:String;
  70. private var dialog:*= null;
  71. private var buttonLoader:Loader;
  72. private var buttonCursorSprite:Sprite;
  73. private var buttonState:uint = 0;
  74. public const BUTTON_STATE_OVER:uint = 1;
  75. public const BUTTON_STATE_DOWN:uint = 2;
  76. public const BUTTON_STATE_DISABLED:uint = 4;
  77. public function Main():void
  78. {
  79. playerID = loaderInfo.parameters.playerID;
  80. if (stage)
  81. init();
  82. else
  83. addEventListener(Event.ADDED_TO_STAGE, init);
  84. }
  85. private function init(e:Event = null):void
  86. {
  87. removeEventListener(Event.ADDED_TO_STAGE, init);
  88. if (!flash.net.FileReference || !flash.external.ExternalInterface || !flash.external.ExternalInterface.available)
  89. return;
  90. // allow uploading to any domain
  91. Security.allowDomain("*");
  92. // ExternalInterface callback adding copied
  93. ExternalInterface.addCallback('initialize', xInitialize);
  94. ExternalInterface.addCallback('setOptions', xSetOptions);
  95. ExternalInterface.addCallback('startUpload', xStart);
  96. ExternalInterface.addCallback('stopUpload', xStop);
  97. ExternalInterface.addCallback('remove', xRemove);
  98. ExternalInterface.addCallback('setEnabled', xSetEnabled);
  99. ExternalInterface.addCallback('fileSetOptions', xFileSetOptions);
  100. ExternalInterface.addCallback('fileStart', xFileStart);
  101. ExternalInterface.addCallback('fileStop', xFileStop);
  102. ExternalInterface.addCallback('fileRemove', xFileRemove);
  103. ExternalInterface.addCallback('fileRequeue', xFileRequeue);
  104. fireEvent('load');
  105. }
  106. public function fireEvent(functionName:String, args:* = null):void
  107. {
  108. verboseLog('Main::fireEvent "' + functionName + '"', args);
  109. if (args !== null) {
  110. if (args is Array) args = Escaper.escapeArray(args);
  111. else args = [Escaper.escape(args)];
  112. }
  113. ExternalInterface.call('apf.flash.callMethod', this.playerID || 1, 'event', functionName, args || []);
  114. }
  115. private function empty(fake:* = null):void
  116. {}
  117. // External Interface - JS to Flash - calls
  118. private function xInitialize(options_override:Object = null):void
  119. {
  120. xSetOptions(options_override);
  121. // Make the stage clickable and transparent.
  122. stage.align = StageAlign.TOP_LEFT;
  123. stage.scaleMode = StageScaleMode.NO_SCALE;
  124. stage.addEventListener(MouseEvent.CLICK, stageClick);
  125. stage.addEventListener(MouseEvent.MOUSE_DOWN, stageMouse);
  126. stage.addEventListener(MouseEvent.MOUSE_UP, stageMouse);
  127. stage.addEventListener(MouseEvent.MOUSE_OVER, stageMouse);
  128. stage.addEventListener(MouseEvent.MOUSE_OUT, stageMouse);
  129. stage.addEventListener(Event.MOUSE_LEAVE, stageLeave);
  130. stage.addEventListener(Event.RESIZE, stageResize);
  131. buttonLoader = new Loader();
  132. buttonLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, empty);
  133. buttonLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, empty);
  134. stage.addChild(buttonLoader);
  135. buttonCursorSprite = new Sprite();
  136. buttonCursorSprite.graphics.beginFill(0xFFFFFF, 0.1);
  137. buttonCursorSprite.graphics.drawRect(0, 0, 1, 1);
  138. buttonCursorSprite.graphics.endFill();
  139. buttonCursorSprite.buttonMode = true;
  140. buttonCursorSprite.useHandCursor = true;
  141. buttonCursorSprite.x = 0;
  142. buttonCursorSprite.y = 0;
  143. buttonCursorSprite.addEventListener(MouseEvent.CLICK, empty);
  144. stage.addChild(buttonCursorSprite);
  145. initButton();
  146. verboseLog('initialized, ' + fileList.length);
  147. }
  148. private function xSetOptions(options_override:Object = null):void
  149. {
  150. if (options_override === null) return;
  151. for (var prop:String in options) {
  152. if (options_override.hasOwnProperty(prop)) {
  153. switch (prop) {
  154. case 'policyFile':
  155. if (options_override[prop] is String)
  156. Security.loadPolicyFile(options_override[prop]);
  157. break;
  158. }
  159. options[prop] = options_override[prop];
  160. }
  161. }
  162. }
  163. private function xFileSetOptions(id:uint, options_init:Object = null):Boolean
  164. {
  165. var ref:File = getFileById(id);
  166. if (!ref) return false;
  167. ref.setOptions(options_init);
  168. return true;
  169. }
  170. private function xFileStart(id:uint):Boolean
  171. {
  172. var ref:File = getFileById(id);
  173. if (!ref) return false;
  174. return ref.start();
  175. }
  176. private function xFileStop(id:uint):Boolean
  177. {
  178. var ref:File = getFileById(id);
  179. if (!ref) return false;
  180. return ref.stop();
  181. }
  182. private function xFileRemove(id:uint):Boolean
  183. {
  184. var ref:File = getFileById(id);
  185. if (!ref) return false;
  186. return ref.remove();
  187. }
  188. public function queueUpdate():Object
  189. {
  190. return {
  191. uploading: uploading,
  192. size: size,
  193. bytesLoaded: bytesLoaded,
  194. percentLoaded: (size > 0) ? Math.ceil(bytesLoaded / size * 100) : 0,
  195. rate: rate
  196. };
  197. }
  198. private function xFileRequeue(id:uint):Boolean
  199. {
  200. var ref:File = getFileById(id);
  201. if (!ref) return false;
  202. return ref.requeue();
  203. }
  204. private function xStart():void
  205. {
  206. if (uploading) return;
  207. checkQueue();
  208. if (uploading)
  209. fireEvent('start');
  210. }
  211. private function xSetEnabled(status:* = null):void
  212. {
  213. if (status == null) status = !(buttonState & BUTTON_STATE_DISABLED);
  214. if (status)
  215. buttonState = buttonState &~ BUTTON_STATE_DISABLED;
  216. else
  217. buttonState = buttonState | BUTTON_STATE_DISABLED;
  218. buttonCursorSprite.useHandCursor = status;
  219. updateButton();
  220. }
  221. private function xStop():void
  222. {
  223. for (var i:uint = fileList.length - 1; i > 0; i--) {
  224. if (fileList[i].status != File.STATUS_RUNNING) continue;
  225. fileList[i].stop();
  226. }
  227. }
  228. private function xRemove():void
  229. {
  230. while (fileList.length) {
  231. fileList[0].remove();
  232. }
  233. }
  234. public function checkQueue(eventful:Boolean = false):void
  235. {
  236. var queued:uint = (options.queued) ? ((options.queued > 1) ? options.queued : 1) : 0;
  237. if (uploading && queued && uploading >= queued) return;
  238. var length:uint = fileList.length;
  239. for (var i:uint = 0; i < length; i++) {
  240. if (fileList[i].status != File.STATUS_QUEUED) continue;
  241. fileList[i].start();
  242. if (queued && uploading >= queued) break;
  243. }
  244. if (!uploading && eventful)
  245. fireEvent('complete', [queueUpdate()]);
  246. }
  247. private function stageClick(e:MouseEvent):void
  248. {
  249. if (buttonState & BUTTON_STATE_DISABLED) {
  250. fireEvent('disabledBrowse');
  251. return;
  252. }
  253. browse();
  254. }
  255. private function stageLeave(e:Event):void
  256. {
  257. buttonState = buttonState &~ BUTTON_STATE_DOWN;
  258. buttonState = buttonState &~ BUTTON_STATE_OVER;
  259. updateButton();
  260. }
  261. private function stageResize(e:Event):void
  262. {
  263. updateSize();
  264. }
  265. private function stageMouse(e:MouseEvent):void
  266. {
  267. switch (e.type) {
  268. case MouseEvent.MOUSE_DOWN:
  269. if (e.buttonDown)
  270. buttonState = buttonState | BUTTON_STATE_DOWN;
  271. break;
  272. case MouseEvent.MOUSE_UP:
  273. buttonState = buttonState &~ BUTTON_STATE_DOWN;
  274. break;
  275. case MouseEvent.MOUSE_OVER:
  276. buttonState = buttonState | BUTTON_STATE_OVER;
  277. break;
  278. case MouseEvent.MOUSE_OUT:
  279. buttonState = buttonState &~ BUTTON_STATE_OVER;
  280. }
  281. updateButton();
  282. }
  283. private function updateSize():void
  284. {
  285. buttonCursorSprite.width = stage.stageWidth;
  286. buttonCursorSprite.height = stage.stageHeight;
  287. }
  288. private function initButton():void
  289. {
  290. if (options.buttonImage) {
  291. buttonLoader.load(new URLRequest(options.buttonImage));
  292. }
  293. else {
  294. buttonLoader.unload();
  295. }
  296. updateSize();
  297. updateButton();
  298. }
  299. private function updateButton():void
  300. {
  301. var to_y:int = 0;
  302. var event:String = 'Leave';
  303. if (buttonState & BUTTON_STATE_DISABLED) {
  304. to_y = stage.stageHeight * -3;
  305. event = 'Disable';
  306. }
  307. else if (buttonState & BUTTON_STATE_DOWN) {
  308. to_y = stage.stageHeight * -2;
  309. event = 'Down';
  310. }
  311. else if (buttonState & BUTTON_STATE_OVER) {
  312. to_y = stage.stageHeight * -1;
  313. event = 'Enter';
  314. }
  315. if (to_y != buttonLoader.y) {
  316. buttonLoader.y = to_y;
  317. fireEvent('button' + event);
  318. }
  319. }
  320. private function browse():void
  321. {
  322. var filter:Array = new Array();
  323. if (options.typeFilter is String) {
  324. var description:String = options.typeFilterDescription || options.typeFilter;
  325. var type:FileFilter = new FileFilter(description, options.typeFilter
  326. + '; ' + options.typeFilter.toUpperCase() + '; '
  327. + options.typeFilter.toLowerCase());
  328. filter.push(type);
  329. }
  330. else if (options.typeFilter is Object) {
  331. for (var key:String in options.typeFilter) {
  332. filter.push(new FileFilter(key, options.typeFilter[key] + '; '
  333. + options.typeFilter[key].toUpperCase() + '; '
  334. + options.typeFilter[key].toLowerCase()));
  335. }
  336. }
  337. fireEvent('browse');
  338. dialog = (options.multiple) ? new FileReferenceList() : new FileReference();
  339. dialog.addEventListener(Event.SELECT, handleSelect);
  340. dialog.addEventListener(Event.CANCEL, handleCancel);
  341. try {
  342. dialog.browse((filter.length) ? filter : null);
  343. }
  344. catch (e:Error) {
  345. verboseLog('Main::browse Exception', e.toString());
  346. }
  347. }
  348. private function handleSelect(event:Event):void
  349. {
  350. verboseLog('Main::handleSelect Adding Files');
  351. var origin:FileReference,
  352. ref:File,
  353. added:Array = new Array();
  354. if (options.multiple) {
  355. var refList:FileReferenceList = dialog;
  356. for (var i:uint = 0; i < refList.fileList.length; i++) {
  357. origin = refList.fileList[i];
  358. ref = new File(this, origin);
  359. added.push(ref);
  360. }
  361. }
  362. else {
  363. origin = dialog;
  364. ref = new File(this, origin);
  365. added.push(ref);
  366. }
  367. var failed:Array = new Array();
  368. added = added.filter(function(ref:File, i:uint, self:Array):Boolean {
  369. if (!ref.validate()) {
  370. ref.id = 0; // invalidate file reference
  371. failed.push(ref);
  372. return false;
  373. }
  374. size += ref.reference.size;
  375. return true;
  376. });
  377. fileList = fileList.concat(added);
  378. if (added.length)
  379. fireEvent('selectSuccess', [File.exportMany(added)]);
  380. if (failed.length)
  381. fireEvent('selectFail', [File.exportMany(failed)]);
  382. fireEvent('queue', [queueUpdate()]);
  383. dialog = null;
  384. }
  385. private function handleCancel(event:Event):void
  386. {
  387. buttonState = buttonState & ~ BUTTON_STATE_OVER;
  388. updateButton();
  389. fireEvent('cancel');
  390. dialog = null;
  391. }
  392. private function getFileById(id:uint):File
  393. {
  394. if (id > 0) {
  395. for (var i:uint = 0; i < fileList.length; i++) {
  396. if (fileList[i].id == id)
  397. return fileList[i];
  398. }
  399. }
  400. verboseLog('Main::getFileById', 'File not found: ' + id);
  401. return null;
  402. }
  403. public function hasFile(check:File):Boolean
  404. {
  405. verboseLog('Main::hasFile', 'Checking ' + check.reference.name);
  406. return fileList.some(function(current:File, i:uint, self:Array):Boolean {
  407. if (current.reference == check.reference) return true;
  408. return (check.reference.name == current.reference.name
  409. && check.reference.size == current.reference.size
  410. && check.reference.creationDate.valueOf() == current.reference.creationDate.valueOf());
  411. }, this);
  412. }
  413. // Misc. helpers
  414. public function verboseLog(labelName:String, message:* = null):void
  415. {
  416. if (!options.verbose) return;
  417. labelName = '[FLASH-VERBOSE] ' + labelName;
  418. if (message)
  419. ExternalInterface.call('apf.console.info', labelName + ':', Escaper.escape(message));
  420. else
  421. ExternalInterface.call('apf.console.info', labelName);
  422. }
  423. }
  424. }