1 // © 2013 Benoît Pin MINES ParisTech
5 // nombre maximun d'image chargées en local
8 DDFileUploader = function(dropbox
, uploadUrl
) {
9 this.dropbox
= dropbox
;
10 this.uploadUrl
= uploadUrl
;
12 this.progressBarMaxSize
= 200; // pixels
13 this.thumbnailSize
= 180;
14 this.previewQueue
= [];
15 this._previewQueueRunning
= false;
16 this.previewsLoaded
= 0;
17 this.uploadQueue
= [];
18 this._uploadQueueRunning
= false;
20 addListener(dropbox
, 'dragenter', function(evt
){self
.dragenter(evt
);});
21 addListener(dropbox
, 'dragover', function(evt
){self
.dragover(evt
);});
22 addListener(dropbox
, 'drop', function(evt
){self
.drop(evt
);});
26 DDFileUploader
.prototype.dragenter = function(evt
) {
28 disablePropagation(evt
);
31 DDFileUploader
.prototype.dragover = function(evt
) {
33 disablePropagation(evt
);
34 evt
= getEventObject(evt
);
35 var dt
= evt
.dataTransfer
;
36 dt
.dropEffect
= 'copy';
39 DDFileUploader
.prototype.drop = function(evt
) {
41 disablePropagation(evt
);
43 var dt
= evt
.dataTransfer
;
44 dt
.dropEffect
= 'copy';
45 this.handleFiles(dt
.files
);
48 // Methods about upload
49 DDFileUploader
.prototype.handleFiles = function(files
) {
51 for (i
= 0; i
< files
.length
; i
++) {
53 slide
= this.createSlide(file
);
54 this.previewQueuePush(slide
);
55 this.uploadQueuePush(slide
);
59 DDFileUploader
.prototype.upload = function(slide
) {
60 var reader
= new FileReader();
61 var req
= new XMLHttpRequest();
62 var file
= slide
.file
;
63 this.uploadedSlide
= slide
;
64 this.previewImg
= slide
.img
;
65 this.progressBar
= slide
.progressBar
;
68 addListener(req
.upload
, 'progress', function(evt
){self
.progressHandler(evt
);});
69 addListener(req
, 'readystatechange',
71 if (req
.readyState
=== 4) {
72 self
.uploadCompleteHandler(req
);
76 req
.open("PUT", this.uploadUrl
);
77 req
.setRequestHeader("Content-Type", file
.type
);
78 req
.setRequestHeader("X-File-Name", file
.name
);
79 addListener(reader
, 'load',
82 req
.sendAsBinary(evt
.target
.result
);
86 reader
.readAsBinaryString(file
);
89 DDFileUploader
.prototype.uploadCompleteHandler = function(req
) {
90 var slide
= this.uploadedSlide
;
91 this.uploadedSlide
.removeChild(slide
.label
);
92 this.uploadedSlide
.removeChild(slide
.progressBar
);
93 var fragment
= getCopyOfNode(req
.responseXML
.documentElement
.firstChild
);
94 var img
= fragment
.getElementsByTagName('img')[0];
95 img
.onload = function(evt
) {
96 // accelerate GC before replacing
98 slide
.img
.parentNode
.removeChild(slide
.img
);
99 slide
.img
= undefined;
100 slide
.parentNode
.replaceChild(fragment
, slide
);
102 this.previewsLoaded
--;
103 this.previewQueueLoadNext();
104 this.uploadQueueLoadNext();
107 DDFileUploader
.prototype.progressHandler = function(evt
) {
108 if (evt
.lengthComputable
) {
109 var progress
= evt
.loaded
/ evt
.total
;
110 this.updateProgressBar(progress
);
111 var currentOpacity
= this.previewImg
.style
.opacity
;
112 this.previewImg
.style
.opacity
= Math
.max(currentOpacity
, progress
);
116 // Method about queues
118 DDFileUploader
.prototype.previewQueuePush = function(slide
) {
119 this.previewQueue
.push(slide
);
120 if (!this._previewQueueRunning
) {
121 this.startPreviewQueue();
125 DDFileUploader
.prototype.startPreviewQueue = function() {
126 this._previewQueueRunning
= true;
127 this.previewQueueLoadNext();
130 DDFileUploader
.prototype.previewQueueLoadNext = function() {
131 if (this.previewQueue
.length
&& this.previewsLoaded
< MAX_PREVIEW
) {
132 var slide
= this.previewQueue
.shift();
133 this.previewUploadedImage(slide
);
134 this.previewsLoaded
++;
137 this._previewQueueRunning
= false;
141 DDFileUploader
.prototype.uploadQueuePush = function(slide
) {
142 this.uploadQueue
.push(slide
);
143 if (!this._uploadQueueRunning
) {
144 this.startUploadQueue();
148 DDFileUploader
.prototype.startUploadQueue = function() {
149 this._uploadQueueRunning
= true;
150 this.uploadQueueLoadNext();
154 DDFileUploader
.prototype.uploadQueueLoadNext = function() {
155 var slide
= this.uploadQueue
.shift();
160 this._uploadQueueRunning
= false;
166 DDFileUploader
.prototype.createSlide = function(file
) {
167 var slide
= document
.createElement('span');
170 var a
= document
.createElement('a');
172 a
.className
= 'slide';
174 var img
= document
.createElement('img');
175 img
.className
= 'hidden';
176 var size
= this.thumbnailSize
;
178 img
.onload = function(evt
) {
179 if (img
.width
> img
.height
) { // landscape
180 img
.height
= Math
.round(size
* img
.height
/ img
.width
);
184 img
.width
= Math
.round(size
* img
.width
/ img
.height
);
187 img
.style
.marginLeft
= Math
.floor((self
.slideSize
- img
.width
) / 2) + 'px';
188 img
.style
.marginTop
= Math
.floor((self
.slideSize
- img
.height
) / 2) + 'px';
189 img
.style
.opacity
= 0.2;
190 img
.className
= undefined;
195 var label
= document
.createElement('span');
197 label
.className
= 'label';
198 label
.innerHTML
= file
.name
;
200 var progressBar
= document
.createElement('span');
201 progressBar
.className
= 'upload-progress';
202 slide
.progressBar
= progressBar
;
204 slide
.appendChild(a
);
205 slide
.appendChild(progressBar
);
206 slide
.appendChild(label
);
207 this.dropbox
.appendChild(slide
);
212 DDFileUploader
.prototype.updateProgressBar = function(progress
) {
213 // 0 <= progress <= 1
214 var size
= this.progressBarMaxSize
* progress
;
215 size
= Math
.round(size
);
216 this.progressBar
.style
.width
= size
+ 'px';
219 DDFileUploader
.prototype.previewUploadedImage = function(slide
) {
220 var reader
= new FileReader();
221 var size
= this.thumbnailSize
;
224 reader
.onload = function(evt
) {
225 slide
.img
.src
= evt
.target
.result
;
226 setTimeout(function(){self
.previewQueueLoadNext();}, 500);
228 reader
.readAsDataURL(slide
.file
);