1 // © 2013 Benoît Pin MINES ParisTech
2 var DDFileUploaderBase
;
5 // nombre maximun d'image chargées en local
8 DDFileUploaderBase = function(dropbox
, uploadUrl
) {
9 this.dropbox
= dropbox
;
10 this.uploadUrl
= uploadUrl
;
11 this.uploadQueue
= [];
12 this._uploadQueueRunning
= false;
14 addListener(dropbox
, 'dragenter', function(evt
){self
.dragenter(evt
);});
15 addListener(dropbox
, 'dragover', function(evt
){self
.dragover(evt
);});
16 addListener(dropbox
, 'drop', function(evt
){self
.drop(evt
);});
20 DDFileUploaderBase
.prototype.dragenter = function(evt
) {
22 disablePropagation(evt
);
25 DDFileUploaderBase
.prototype.dragover = function(evt
) {
27 disablePropagation(evt
);
28 evt
= getEventObject(evt
);
29 var dt
= evt
.dataTransfer
;
30 dt
.dropEffect
= 'copy';
33 DDFileUploaderBase
.prototype.drop = function(evt
) {
35 disablePropagation(evt
);
37 var dt
= evt
.dataTransfer
;
38 dt
.dropEffect
= 'copy';
39 this.handleFiles(dt
.files
);
42 // Methods about upload
43 DDFileUploaderBase
.prototype.handleFiles = function(files
) {
45 for (i
= 0; i
< files
.length
; i
++) {
47 slide
= this.createSlide(file
);
48 this.previewQueuePush(slide
);
49 this.uploadQueuePush(slide
);
53 DDFileUploaderBase
.prototype.upload = function(slide
) {
54 var reader
= new FileReader();
55 var req
= new XMLHttpRequest();
56 var file
= slide
.file
;
57 this.uploadedSlide
= slide
;
58 this.previewImg
= slide
.img
;
59 this.progressBar
= slide
.progressBar
;
62 addListener(req
.upload
, 'progress', function(evt
){self
.progressHandler(evt
);});
63 addListener(req
, 'readystatechange',
65 if (req
.readyState
=== 4) {
66 self
.uploadCompleteHandler(req
);
70 req
.open("PUT", this.uploadUrl
);
71 req
.setRequestHeader("Content-Type", file
.type
);
72 req
.setRequestHeader("X-File-Name", file
.name
);
73 addListener(reader
, 'load',
76 req
.sendAsBinary(evt
.target
.result
);
80 reader
.readAsBinaryString(file
);
83 DDFileUploaderBase
.prototype.uploadCompleteHandler = function(req
) {
84 var slide
= this.uploadedSlide
;
85 this.uploadedSlide
.removeChild(slide
.label
);
86 this.uploadedSlide
.removeChild(slide
.progressBar
);
87 var fragment
= getCopyOfNode(req
.responseXML
.documentElement
.firstChild
);
88 var img
= fragment
.getElementsByTagName('img')[0];
89 if (req
.status
=== 200) {
91 var existing
= this.existingSlides
[img
.src
];
93 existing
.src
= existing
.src
+ '?' + Math
.random().toString();
96 slide
.img
.parentNode
.removeChild(slide
.img
);
97 slide
.img
= undefined;
98 slide
.parentNode
.removeChild(slide
);
100 else if(req
.status
=== 201) {
102 img
.onload = function(evt
) {
103 // accelerate GC before replacing
105 slide
.img
.parentNode
.removeChild(slide
.img
);
106 slide
.img
= undefined;
107 slide
.parentNode
.replaceChild(fragment
, slide
);
110 this.previewsLoaded
--;
111 this.previewQueueLoadNext();
112 this.uploadQueueLoadNext();
115 DDFileUploaderBase
.prototype.progressHandler = function(evt
) {
116 if (evt
.lengthComputable
) {
117 var progress
= evt
.loaded
/ evt
.total
;
118 this.updateProgressBar(progress
);
119 var currentOpacity
= this.previewImg
.style
.opacity
;
120 this.previewImg
.style
.opacity
= Math
.max(currentOpacity
, progress
);
124 // Method about queues
126 DDFileUploaderBase
.prototype.previewQueuePush = function(slide
) {
127 this.previewQueue
.push(slide
);
128 if (!this._previewQueueRunning
) {
129 this.startPreviewQueue();
133 DDFileUploaderBase
.prototype.startPreviewQueue = function() {
134 this._previewQueueRunning
= true;
135 this.previewQueueLoadNext();
138 DDFileUploaderBase
.prototype.previewQueueLoadNext = function() {
139 if (this.previewQueue
.length
&& this.previewsLoaded
< MAX_PREVIEW
) {
140 var slide
= this.previewQueue
.shift();
141 this.previewUploadedImage(slide
);
142 this.previewsLoaded
++;
145 this._previewQueueRunning
= false;
149 DDFileUploaderBase
.prototype.uploadQueuePush = function(slide
) {
150 this.uploadQueue
.push(slide
);
151 if (!this._uploadQueueRunning
) {
152 this.startUploadQueue();
156 DDFileUploaderBase
.prototype.startUploadQueue = function() {
157 this._uploadQueueRunning
= true;
158 this.uploadQueueLoadNext();
162 DDFileUploaderBase
.prototype.uploadQueueLoadNext = function() {
163 var slide
= this.uploadQueue
.shift();
168 this._uploadQueueRunning
= false;
174 DDFileUploaderBase
.prototype.createSlide = function(file
) {
175 var slide
= document
.createElement('span');
178 var a
= document
.createElement('a');
180 a
.className
= 'slide';
182 var img
= document
.createElement('img');
183 img
.className
= 'hidden';
184 var size
= this.thumbnailSize
;
186 img
.onload = function(evt
) {
187 if (img
.width
> img
.height
) { // landscape
188 img
.height
= Math
.round(size
* img
.height
/ img
.width
);
192 img
.width
= Math
.round(size
* img
.width
/ img
.height
);
195 img
.style
.marginLeft
= Math
.floor((self
.slideSize
- img
.width
) / 2) + 'px';
196 img
.style
.marginTop
= Math
.floor((self
.slideSize
- img
.height
) / 2) + 'px';
197 img
.style
.opacity
= 0.2;
198 img
.className
= undefined;
203 var label
= document
.createElement('span');
205 label
.className
= 'label';
206 label
.innerHTML
= file
.name
;
208 var progressBar
= document
.createElement('span');
209 progressBar
.className
= 'upload-progress';
210 slide
.progressBar
= progressBar
;
212 slide
.appendChild(a
);
213 slide
.appendChild(progressBar
);
214 slide
.appendChild(label
);
215 this.dropbox
.appendChild(slide
);
220 DDFileUploaderBase
.prototype.updateProgressBar = function(progress
) {
221 // 0 <= progress <= 1
222 var size
= this.progressBarMaxSize
* progress
;
223 size
= Math
.round(size
);
224 this.progressBar
.style
.width
= size
+ 'px';
227 DDFileUploaderBase
.prototype.previewUploadedImage = function(slide
) {
228 var reader
= new FileReader();
229 var size
= this.thumbnailSize
;
232 reader
.onload = function(evt
) {
233 slide
.img
.src
= evt
.target
.result
;
234 setTimeout(function(){self
.previewQueueLoadNext();}, 500);
236 reader
.readAsDataURL(slide
.file
);