PageRenderTime 39ms CodeModel.GetById 13ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

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