2
* Default text - jQuery plugin for html5 dragging files from desktop to browser
6
* Email: [Firstname][Lastname]@gmail.com
8
* Copyright (c) 2010 Resopollution
10
* Licensed under the MIT license:
11
* http://www.opensource.org/licenses/mit-license.php
14
* http://www.github.com/weixiyen/jquery-filedrop
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)
23
* See README at project homepage
28
jQuery.event.props.push("dataTransfer");
33
paramname: 'userfile',
35
maxfilesize: 1, // MBs
47
error: function(err, file, i){alert(err);},
49
uploadFinished: empty,
50
progressUpdated: empty,
53
errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge"],
59
$.fn.filedrop = function(options) {
60
opts = $.extend( {}, default_opts, options );
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);
68
files = e.dataTransfer.files;
69
if (files === null || files === undefined) {
70
opts.error(errors[0]);
74
files_count = files.length;
80
function getBuilder(filename, filedata, boundary) {
85
$.each(opts.data, function(i, val) {
86
if (typeof val === 'function') val = val();
90
builder += 'Content-Disposition: form-data; name="'+i+'"';
100
builder += 'Content-Disposition: form-data; name="'+opts.paramname+'"';
101
builder += '; filename="' + filename + '"';
104
builder += 'Content-Type: application/octet-stream';
118
function progress(e) {
119
if (e.lengthComputable) {
120
var percentage = Math.round((e.loaded * 100) / e.total);
121
if (this.currentProgress != percentage) {
123
this.currentProgress = percentage;
124
opts.progressUpdated(this.index, this.file, this.currentProgress);
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;
144
opts.error(errors[0]);
150
if (files_count > opts.maxfiles) {
151
opts.error(errors[1]);
155
for (var i=0; i<files_count; i++) {
156
if (stop_loop) return false;
158
if (beforeEach(files[i]) != false) {
159
if (i === files_count) return;
160
var reader = new FileReader(),
161
max_file_size = 1048576 * opts.maxfilesize;
164
if (files[i].size > max_file_size) {
165
opts.error(errors[2], files[i], i);
170
reader.onloadend = send;
171
reader.readAsBinaryString(files[i]);
176
opts.error(errors[0]);
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);
188
var xhr = new XMLHttpRequest(),
190
file = files[e.target.index],
191
index = e.target.index,
192
start_time = new Date().getTime(),
193
boundary = '------multipartformboundary' + (new Date).getTime(),
196
newName = rename(file.name);
197
if (typeof newName === "string") {
198
builder = getBuilder(newName, e.target.result, boundary);
200
builder = getBuilder(file.name, e.target.result, boundary);
203
upload.index = index;
205
upload.downloadStartTime = start_time;
206
upload.currentStart = start_time;
207
upload.currentProgress = 0;
208
upload.startData = 0;
209
upload.addEventListener("progress", progress, false);
211
xhr.open("POST", opts.url, true);
212
xhr.setRequestHeader('content-type', 'multipart/form-data; boundary='
215
xhr.sendAsBinary(builder);
217
opts.uploadStarted(index, file, files_count);
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);
225
if (filesDone == files_count - filesRejected) {
228
if (result === false) stop_loop = true;
234
function getIndexBySize(size) {
235
for (var i=0; i < files_count; i++) {
236
if (files[i].size == size) {
244
function rename(name) {
245
return opts.rename(name);
248
function beforeEach(file) {
249
return opts.beforeEach(file);
252
function afterAll() {
253
return opts.afterAll();
256
function dragEnter(e) {
257
clearTimeout(doc_leave_timer);
262
function dragOver(e) {
263
clearTimeout(doc_leave_timer);
269
function dragLeave(e) {
270
clearTimeout(doc_leave_timer);
275
function docDrop(e) {
281
function docEnter(e) {
282
clearTimeout(doc_leave_timer);
288
function docOver(e) {
289
clearTimeout(doc_leave_timer);
295
function docLeave(e) {
296
doc_leave_timer = setTimeout(function(){
304
if (XMLHttpRequest.prototype.sendAsBinary) return;
305
XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
306
function byteValue(x) {
307
return x.charCodeAt(0) & 0xff;
309
var ords = Array.prototype.map.call(datastr, byteValue);
310
var ui8a = new Uint8Array(ords);
311
this.send(ui8a.buffer);
b'\\ No newline at end of file'