/media/system/js/swf-uncompressed.js

https://bitbucket.org/eternaware/joomus · JavaScript · 490 lines · 344 code · 92 blank · 54 comment · 65 complexity · df0efb1df295efc80b72bb0fa729561f MD5 · raw file

  1. /**
  2. * Swiff.Uploader - Flash FileReference Control
  3. *
  4. * @version 3.0
  5. *
  6. * @license MIT License
  7. *
  8. * @author Harald Kirschner <http://digitarald.de>
  9. * @author Valerio Proietti, <http://mad4milk.net>
  10. * @copyright Authors
  11. */
  12. Swiff.Uploader = new Class({
  13. Extends: Swiff,
  14. Implements: Events,
  15. options: {
  16. path: 'Swiff.Uploader.swf',
  17. target: null,
  18. zIndex: 9999,
  19. callBacks: null,
  20. params: {
  21. wMode: 'opaque',
  22. menu: 'false',
  23. allowScriptAccess: 'always'
  24. },
  25. typeFilter: null,
  26. multiple: true,
  27. queued: true,
  28. verbose: false,
  29. height: 30,
  30. width: 100,
  31. passStatus: null,
  32. url: null,
  33. method: null,
  34. data: null,
  35. mergeData: true,
  36. fieldName: null,
  37. fileSizeMin: 1,
  38. fileSizeMax: null, // Official limit is 100 MB for FileReference, but I tested up to 2Gb!
  39. allowDuplicates: false,
  40. timeLimit: (Browser.Platform.linux) ? 0 : 30,
  41. policyFile: null,
  42. buttonImage: null,
  43. fileListMax: 0,
  44. fileListSizeMax: 0,
  45. instantStart: false,
  46. appendCookieData: false,
  47. fileClass: null
  48. /*
  49. onLoad: $empty,
  50. onFail: $empty,
  51. onStart: $empty,
  52. onQueue: $empty,
  53. onComplete: $empty,
  54. onBrowse: $empty,
  55. onDisabledBrowse: $empty,
  56. onCancel: $empty,
  57. onSelect: $empty,
  58. onSelectSuccess: $empty,
  59. onSelectFail: $empty,
  60. onButtonEnter: $empty,
  61. onButtonLeave: $empty,
  62. onButtonDown: $empty,
  63. onButtonDisable: $empty,
  64. onFileStart: $empty,
  65. onFileStop: $empty,
  66. onFileRequeue: $empty,
  67. onFileOpen: $empty,
  68. onFileProgress: $empty,
  69. onFileComplete: $empty,
  70. onFileRemove: $empty,
  71. onBeforeStart: $empty,
  72. onBeforeStop: $empty,
  73. onBeforeRemove: $empty
  74. */
  75. },
  76. initialize: function(options) {
  77. // protected events to control the class, added
  78. // before setting options (which adds own events)
  79. this.addEvent('load', this.initializeSwiff, true)
  80. .addEvent('select', this.processFiles, true)
  81. .addEvent('complete', this.update, true)
  82. .addEvent('fileRemove', function(file) {
  83. this.fileList.erase(file);
  84. }.bind(this), true);
  85. this.setOptions(options);
  86. // callbacks are no longer in the options, every callback
  87. // is fired as event, this is just compat
  88. if (this.options.callBacks) {
  89. Hash.each(this.options.callBacks, function(fn, name) {
  90. this.addEvent(name, fn);
  91. }, this);
  92. }
  93. this.options.callBacks = {
  94. fireCallback: this.fireCallback.bind(this)
  95. };
  96. var path = this.options.path;
  97. if (!path.contains('?')) path += '?noCache=' + Date.now; // cache in IE
  98. // container options for Swiff class
  99. this.options.container = this.box = new Element('span', {'class': 'swiff-uploader-box'}).inject(document.id(this.options.container) || document.body);
  100. // target
  101. this.target = document.id(this.options.target);
  102. if (this.target) {
  103. var scroll = window.getScroll();
  104. this.box.setStyles({
  105. position: 'absolute',
  106. visibility: 'visible',
  107. zIndex: this.options.zIndex,
  108. overflow: 'hidden',
  109. height: 1, width: 1,
  110. top: scroll.y, left: scroll.x
  111. });
  112. // we force wMode to transparent for the overlay effect
  113. this.parent(path, {
  114. params: {
  115. wMode: 'transparent'
  116. },
  117. height: '100%',
  118. width: '100%'
  119. });
  120. this.target.addEvent('mouseenter', this.reposition.bind(this, []));
  121. // button interactions, relayed to to the target
  122. this.addEvents({
  123. buttonEnter: this.targetRelay.bind(this, ['mouseenter']),
  124. buttonLeave: this.targetRelay.bind(this, ['mouseleave']),
  125. buttonDown: this.targetRelay.bind(this, ['mousedown']),
  126. buttonDisable: this.targetRelay.bind(this, ['disable'])
  127. });
  128. this.reposition();
  129. window.addEvent('resize', this.reposition.bind(this, []));
  130. } else {
  131. this.parent(path);
  132. }
  133. this.inject(this.box);
  134. this.fileList = [];
  135. this.size = this.uploading = this.bytesLoaded = this.percentLoaded = 0;
  136. if (Browser.Plugins.Flash.version < 9) {
  137. this.fireEvent('fail', ['flash']);
  138. } else {
  139. this.verifyLoad.delay(1000, this);
  140. }
  141. },
  142. verifyLoad: function() {
  143. if (this.loaded) return;
  144. if (!this.object.parentNode) {
  145. this.fireEvent('fail', ['disabled']);
  146. } else if (this.object.style.display == 'none') {
  147. this.fireEvent('fail', ['hidden']);
  148. } else if (!this.object.offsetWidth) {
  149. this.fireEvent('fail', ['empty']);
  150. }
  151. },
  152. fireCallback: function(name, args) {
  153. // file* callbacks are relayed to the specific file
  154. if (name.substr(0, 4) == 'file') {
  155. // updated queue data is the second argument
  156. if (args.length > 1) this.update(args[1]);
  157. var data = args[0];
  158. var file = this.findFile(data.id);
  159. this.fireEvent(name, file || data, 5);
  160. if (file) {
  161. var fire = name.replace(/^file([A-Z])/, function($0, $1) {
  162. return $1.toLowerCase();
  163. });
  164. file.update(data).fireEvent(fire, [data], 10);
  165. }
  166. } else {
  167. this.fireEvent(name, args, 5);
  168. }
  169. },
  170. update: function(data) {
  171. // the data is saved right to the instance
  172. Object.append(this, data);
  173. this.fireEvent('queue', [this], 10);
  174. return this;
  175. },
  176. findFile: function(id) {
  177. for (var i = 0; i < this.fileList.length; i++) {
  178. if (this.fileList[i].id == id) return this.fileList[i];
  179. }
  180. return null;
  181. },
  182. initializeSwiff: function() {
  183. // extracted options for the swf
  184. this.remote('xInitialize', {
  185. typeFilter: this.options.typeFilter,
  186. multiple: this.options.multiple,
  187. queued: this.options.queued,
  188. verbose: this.options.verbose,
  189. width: this.options.width,
  190. height: this.options.height,
  191. passStatus: this.options.passStatus,
  192. url: this.options.url,
  193. method: this.options.method,
  194. data: this.options.data,
  195. mergeData: this.options.mergeData,
  196. fieldName: this.options.fieldName,
  197. fileSizeMin: this.options.fileSizeMin,
  198. fileSizeMax: this.options.fileSizeMax,
  199. allowDuplicates: this.options.allowDuplicates,
  200. timeLimit: this.options.timeLimit,
  201. policyFile: this.options.policyFile,
  202. buttonImage: this.options.buttonImage
  203. });
  204. this.loaded = true;
  205. this.appendCookieData();
  206. },
  207. targetRelay: function(name) {
  208. if (this.target) this.target.fireEvent(name);
  209. },
  210. reposition: function(coords) {
  211. // update coordinates, manual or automatically
  212. coords = coords || (this.target && this.target.offsetHeight)
  213. ? this.target.getCoordinates(this.box.getOffsetParent())
  214. : {top: window.getScrollTop(), left: 0, width: 40, height: 40}
  215. this.box.setStyles(coords);
  216. this.fireEvent('reposition', [coords, this.box, this.target]);
  217. },
  218. setOptions: function(options) {
  219. if (options) {
  220. if (options.url) options.url = Swiff.Uploader.qualifyPath(options.url);
  221. if (options.buttonImage) options.buttonImage = Swiff.Uploader.qualifyPath(options.buttonImage);
  222. this.parent(options);
  223. if (this.loaded) this.remote('xSetOptions', options);
  224. }
  225. return this;
  226. },
  227. setEnabled: function(status) {
  228. this.remote('xSetEnabled', status);
  229. },
  230. start: function() {
  231. this.fireEvent('beforeStart');
  232. this.remote('xStart');
  233. },
  234. stop: function() {
  235. this.fireEvent('beforeStop');
  236. this.remote('xStop');
  237. },
  238. remove: function() {
  239. this.fireEvent('beforeRemove');
  240. this.remote('xRemove');
  241. },
  242. fileStart: function(file) {
  243. this.remote('xFileStart', file.id);
  244. },
  245. fileStop: function(file) {
  246. this.remote('xFileStop', file.id);
  247. },
  248. fileRemove: function(file) {
  249. this.remote('xFileRemove', file.id);
  250. },
  251. fileRequeue: function(file) {
  252. this.remote('xFileRequeue', file.id);
  253. },
  254. appendCookieData: function() {
  255. var append = this.options.appendCookieData;
  256. if (!append) return;
  257. var hash = {};
  258. document.cookie.split(/;\s*/).each(function(cookie) {
  259. cookie = cookie.split('=');
  260. if (cookie.length == 2) {
  261. hash[decodeURIComponent(cookie[0])] = decodeURIComponent(cookie[1]);
  262. }
  263. });
  264. var data = this.options.data || {};
  265. if ($type(append) == 'string') data[append] = hash;
  266. else Object.append(data, hash);
  267. this.setOptions({data: data});
  268. },
  269. processFiles: function(successraw, failraw, queue) {
  270. var cls = this.options.fileClass || Swiff.Uploader.File;
  271. var fail = [], success = [];
  272. if (successraw) {
  273. successraw.each(function(data) {
  274. var ret = new cls(this, data);
  275. if (!ret.validate()) {
  276. ret.remove.delay(10, ret);
  277. fail.push(ret);
  278. } else {
  279. this.size += data.size;
  280. this.fileList.push(ret);
  281. success.push(ret);
  282. ret.render();
  283. }
  284. }, this);
  285. this.fireEvent('selectSuccess', [success], 10);
  286. }
  287. if (failraw || fail.length) {
  288. fail.extend((failraw) ? failraw.map(function(data) {
  289. return new cls(this, data);
  290. }, this) : []).each(function(file) {
  291. file.invalidate().render();
  292. });
  293. this.fireEvent('selectFail', [fail], 10);
  294. }
  295. this.update(queue);
  296. if (this.options.instantStart && success.length) this.start();
  297. }
  298. });
  299. Object.append(Swiff.Uploader, {
  300. STATUS_QUEUED: 0,
  301. STATUS_RUNNING: 1,
  302. STATUS_ERROR: 2,
  303. STATUS_COMPLETE: 3,
  304. STATUS_STOPPED: 4,
  305. log: function() {
  306. if (window.console && console.info) console.info.apply(console, arguments);
  307. },
  308. unitLabels: {
  309. b: [{min: 1, unit: 'B'}, {min: 1024, unit: 'kB'}, {min: 1048576, unit: 'MB'}, {min: 1073741824, unit: 'GB'}],
  310. s: [{min: 1, unit: 's'}, {min: 60, unit: 'm'}, {min: 3600, unit: 'h'}, {min: 86400, unit: 'd'}]
  311. },
  312. formatUnit: function(base, type, join) {
  313. var labels = Swiff.Uploader.unitLabels[(type == 'bps') ? 'b' : type];
  314. var append = (type == 'bps') ? '/s' : '';
  315. var i, l = labels.length, value;
  316. if (base < 1) return '0 ' + labels[0].unit + append;
  317. if (type == 's') {
  318. var units = [];
  319. for (i = l - 1; i >= 0; i--) {
  320. value = Math.floor(base / labels[i].min);
  321. if (value) {
  322. units.push(value + ' ' + labels[i].unit);
  323. base -= value * labels[i].min;
  324. if (!base) break;
  325. }
  326. }
  327. return (join === false) ? units : units.join(join || ', ');
  328. }
  329. for (i = l - 1; i >= 0; i--) {
  330. value = labels[i].min;
  331. if (base >= value) break;
  332. }
  333. return (base / value).toFixed(1) + ' ' + labels[i].unit + append;
  334. }
  335. });
  336. Swiff.Uploader.qualifyPath = (function() {
  337. var anchor;
  338. return function(path) {
  339. (anchor || (anchor = new Element('a'))).href = path;
  340. return anchor.href;
  341. };
  342. })();
  343. Swiff.Uploader.File = new Class({
  344. Implements: Events,
  345. initialize: function(base, data) {
  346. this.base = base;
  347. this.update(data);
  348. },
  349. update: function(data) {
  350. return Object.append(this, data);
  351. },
  352. validate: function() {
  353. var options = this.base.options;
  354. if (options.fileListMax && this.base.fileList.length >= options.fileListMax) {
  355. this.validationError = 'fileListMax';
  356. return false;
  357. }
  358. if (options.fileListSizeMax && (this.base.size + this.size) > options.fileListSizeMax) {
  359. this.validationError = 'fileListSizeMax';
  360. return false;
  361. }
  362. return true;
  363. },
  364. invalidate: function() {
  365. this.invalid = true;
  366. this.base.fireEvent('fileInvalid', this, 10);
  367. return this.fireEvent('invalid', this, 10);
  368. },
  369. render: function() {
  370. return this;
  371. },
  372. setOptions: function(options) {
  373. if (options) {
  374. if (options.url) options.url = Swiff.Uploader.qualifyPath(options.url);
  375. this.base.remote('xFileSetOptions', this.id, options);
  376. this.options = $merge(this.options, options);
  377. }
  378. return this;
  379. },
  380. start: function() {
  381. this.base.fileStart(this);
  382. return this;
  383. },
  384. stop: function() {
  385. this.base.fileStop(this);
  386. return this;
  387. },
  388. remove: function() {
  389. this.base.fileRemove(this);
  390. return this;
  391. },
  392. requeue: function() {
  393. this.base.fileRequeue(this);
  394. }
  395. });