/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk
20.1.1 by galaxyAbstractor
* Added an simple admin panel to the codeviewer-cmssy stuff
1
/*
2
 * Default text - jQuery plugin for html5 dragging files from desktop to browser
3
 *
4
 * Author: Weixi Yen
5
 *
6
 * Email: [Firstname][Lastname]@gmail.com
7
 * 
8
 * Copyright (c) 2010 Resopollution
9
 * 
10
 * Licensed under the MIT license:
11
 *   http://www.opensource.org/licenses/mit-license.php
12
 *
13
 * Project home:
14
 *   http://www.github.com/weixiyen/jquery-filedrop
15
 *
16
 * Version:  0.1.0
17
 *
18
 * Features:
19
 *      Allows sending of extra parameters with file.
20
 *      Works with Firefox 3.6+
21
 *      Future-compliant with HTML5 spec (will work with Webkit browsers and IE9)
22
 * Usage:
23
 * 	See README at project homepage
24
 *
25
 */
26
(function($){
27
28
	jQuery.event.props.push("dataTransfer");
29
	var opts = {},
30
		default_opts = {
31
			url: '',
32
			refresh: 1000,
33
			paramname: 'userfile',
34
			maxfiles: 25,
35
			maxfilesize: 1, // MBs
36
			data: {},
37
			drop: empty,
38
			dragEnter: empty,
39
			dragOver: empty,
40
			dragLeave: empty,
41
			docEnter: empty,
42
			docOver: empty,
43
			docLeave: empty,
44
			beforeEach: empty,
45
			afterAll: empty,
46
			rename: empty,
47
			error: function(err, file, i){alert(err);},
48
			uploadStarted: empty,
49
			uploadFinished: empty,
50
			progressUpdated: empty,
51
			speedUpdated: empty
52
		},
53
		errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge"],
54
		doc_leave_timer,
55
		stop_loop = false,
56
		files_count = 0,
57
		files;
58
59
	$.fn.filedrop = function(options) {
60
		opts = $.extend( {}, default_opts, options );
61
		
62
		this.bind('drop', drop).bind('dragenter', dragEnter).bind('dragover', dragOver).bind('dragleave', dragLeave);
63
		$(document).bind('drop', docDrop).bind('dragenter', docEnter).bind('dragover', docOver).bind('dragleave', docLeave);
64
	};
65
     
66
	function drop(e) {
67
		opts.drop(e);
68
		files = e.dataTransfer.files;
69
		if (files === null || files === undefined) {
70
			opts.error(errors[0]);
71
			return false;
72
		}
73
		
74
		files_count = files.length;
75
		upload();
76
		e.preventDefault();
77
		return false;
78
	}
79
	
80
	function getBuilder(filename, filedata, boundary) {
81
		var dashdash = '--',
82
			crlf = '\r\n',
83
			builder = '';
84
85
		$.each(opts.data, function(i, val) {
86
	    	if (typeof val === 'function') val = val();
87
			builder += dashdash;
88
			builder += boundary;
89
			builder += crlf;
90
			builder += 'Content-Disposition: form-data; name="'+i+'"';
91
			builder += crlf;
92
			builder += crlf;
93
			builder += val;
94
			builder += crlf;
95
		});
96
		
97
		builder += dashdash;
98
		builder += boundary;
99
		builder += crlf;
100
		builder += 'Content-Disposition: form-data; name="'+opts.paramname+'"';
101
		builder += '; filename="' + filename + '"';
102
		builder += crlf;
103
		
104
		builder += 'Content-Type: application/octet-stream';
105
		builder += crlf;
106
		builder += crlf; 
107
		
108
		builder += filedata;
109
		builder += crlf;
110
        
111
		builder += dashdash;
112
		builder += boundary;
113
		builder += dashdash;
114
		builder += crlf;
115
		return builder;
116
	}
117
118
	function progress(e) {
119
		if (e.lengthComputable) {
120
			var percentage = Math.round((e.loaded * 100) / e.total);
121
			if (this.currentProgress != percentage) {
122
				
123
				this.currentProgress = percentage;
124
				opts.progressUpdated(this.index, this.file, this.currentProgress);
125
				
126
				var elapsed = new Date().getTime();
127
				var diffTime = elapsed - this.currentStart;
128
				if (diffTime >= opts.refresh) {
129
					var diffData = e.loaded - this.startData;
130
					var speed = diffData / diffTime; // KB per second
131
					opts.speedUpdated(this.index, this.file, speed);
132
					this.startData = e.loaded;
133
					this.currentStart = elapsed;
134
				}
135
			}
136
		}
137
	}
138
    
139
    
140
    
141
	function upload() {
142
		stop_loop = false;
143
		if (!files) {
144
			opts.error(errors[0]);
145
			return false;
146
		}
147
		var filesDone = 0,
148
			filesRejected = 0;
149
		
150
		if (files_count > opts.maxfiles) {
151
		    opts.error(errors[1]);
152
		    return false;
153
		}
154
155
		for (var i=0; i<files_count; i++) {
156
			if (stop_loop) return false;
157
			try {
158
				if (beforeEach(files[i]) != false) {
159
					if (i === files_count) return;
160
					var reader = new FileReader(),
161
						max_file_size = 1048576 * opts.maxfilesize;
162
						
163
					reader.index = i;
164
					if (files[i].size > max_file_size) {
165
						opts.error(errors[2], files[i], i);
166
						filesRejected++;
167
						continue;
168
					}
169
					
170
					reader.onloadend = send;
171
					reader.readAsBinaryString(files[i]);
172
				} else {
173
					filesRejected++;
174
				}
175
			} catch(err) {
176
				opts.error(errors[0]);
177
				return false;
178
			}
179
		}
180
	    
181
		function send(e) {
182
			// Sometimes the index is not attached to the
183
			// event object. Find it by size. Hack for sure.
184
			if (e.target.index == undefined) {
185
				e.target.index = getIndexBySize(e.total);
186
			}
187
			
188
			var xhr = new XMLHttpRequest(),
189
				upload = xhr.upload,
190
				file = files[e.target.index],
191
				index = e.target.index,
192
				start_time = new Date().getTime(),
193
				boundary = '------multipartformboundary' + (new Date).getTime(),
194
				builder;
195
				
196
			newName = rename(file.name);
197
			if (typeof newName === "string") {
198
				builder = getBuilder(newName, e.target.result, boundary);
199
			} else {
200
				builder = getBuilder(file.name, e.target.result, boundary);
201
			}
202
			
203
			upload.index = index;
204
			upload.file = file;
205
			upload.downloadStartTime = start_time;
206
			upload.currentStart = start_time;
207
			upload.currentProgress = 0;
208
			upload.startData = 0;
209
			upload.addEventListener("progress", progress, false);
210
			
211
			xhr.open("POST", opts.url, true);
212
			xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=' 
213
			    + boundary);
214
			    
215
			xhr.sendAsBinary(builder);  
216
			
217
			opts.uploadStarted(index, file, files_count);  
218
			
219
			xhr.onload = function() { 
220
			    if (xhr.responseText) {
221
				var now = new Date().getTime(),
222
				    timeDiff = now - start_time,
223
				    result = opts.uploadFinished(index, file, jQuery.parseJSON(xhr.responseText), timeDiff);
224
					filesDone++;
225
					if (filesDone == files_count - filesRejected) {
226
						afterAll();
227
					}
228
			    if (result === false) stop_loop = true;
229
			    }
230
			};
231
		}
232
	}
233
    
234
	function getIndexBySize(size) {
235
		for (var i=0; i < files_count; i++) {
236
			if (files[i].size == size) {
237
				return i;
238
			}
239
		}
240
		
241
		return undefined;
242
	}
243
    
244
	function rename(name) {
245
		return opts.rename(name);
246
	}
247
	
248
	function beforeEach(file) {
249
		return opts.beforeEach(file);
250
	}
251
	
252
	function afterAll() {
253
		return opts.afterAll();
254
	}
255
	
256
	function dragEnter(e) {
257
		clearTimeout(doc_leave_timer);
258
		e.preventDefault();
259
		opts.dragEnter(e);
260
	}
261
	
262
	function dragOver(e) {
263
		clearTimeout(doc_leave_timer);
264
		e.preventDefault();
265
		opts.docOver(e);
266
		opts.dragOver(e);
267
	}
268
	 
269
	function dragLeave(e) {
270
		clearTimeout(doc_leave_timer);
271
		opts.dragLeave(e);
272
		e.stopPropagation();
273
	}
274
	 
275
	function docDrop(e) {
276
		e.preventDefault();
277
		opts.docLeave(e);
278
		return false;
279
	}
280
	 
281
	function docEnter(e) {
282
		clearTimeout(doc_leave_timer);
283
		e.preventDefault();
284
		opts.docEnter(e);
285
		return false;
286
	}
287
	 
288
	function docOver(e) {
289
		clearTimeout(doc_leave_timer);
290
		e.preventDefault();
291
		opts.docOver(e);
292
		return false;
293
	}
294
	 
295
	function docLeave(e) {
296
		doc_leave_timer = setTimeout(function(){
297
			opts.docLeave(e);
298
		}, 200);
299
	}
300
	 
301
	function empty(){}
302
	
303
	try {
304
		if (XMLHttpRequest.prototype.sendAsBinary) return;
305
		XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
306
		    function byteValue(x) {
307
		        return x.charCodeAt(0) & 0xff;
308
		    }
309
		    var ords = Array.prototype.map.call(datastr, byteValue);
310
		    var ui8a = new Uint8Array(ords);
311
		    this.send(ui8a.buffer);
312
		}
313
	} catch(e) {}
314
     
315
})(jQuery);