1 // © 2013 Benoît Pin MINES ParisTech
2 var DDFileUploaderBase
;
6 DDFileUploaderBase = function(dropbox
, uploadUrl
) {
7 this.dropbox
= dropbox
;
8 this.uploadUrl
= uploadUrl
;
10 this._uploadQueueRunning
= false;
12 addListener(dropbox
, 'dragenter', function(evt
){self
.dragenter(evt
);});
13 addListener(dropbox
, 'dragover', function(evt
){self
.dragover(evt
);});
14 addListener(dropbox
, 'drop', function(evt
){self
.drop(evt
);});
18 DDFileUploaderBase
.prototype.dragenter = function(evt
) {
20 disablePropagation(evt
);
23 DDFileUploaderBase
.prototype.dragover = function(evt
) {
25 disablePropagation(evt
);
26 evt
= getEventObject(evt
);
27 var dt
= evt
.dataTransfer
;
28 dt
.dropEffect
= 'copy';
31 DDFileUploaderBase
.prototype.drop = function(evt
) {
33 disablePropagation(evt
);
35 var dt
= evt
.dataTransfer
;
36 dt
.dropEffect
= 'copy';
37 this.handleFiles(dt
.files
);
40 // Methods about upload
41 DDFileUploaderBase
.prototype.handleFiles = function(files
) {
42 // To be implemented by descendant.
45 DDFileUploaderBase
.prototype.upload = function(slide
) {
46 var reader
= new FileReader();
47 var req
= new XMLHttpRequest();
48 var file
= slide
.file
;
49 this.uploadedSlide
= slide
;
50 this.previewImg
= slide
.img
;
51 this.progressBar
= slide
.progressBar
;
54 addListener(req
.upload
, 'progress', function(evt
){self
.progressHandler(evt
);});
55 addListener(req
, 'readystatechange',
57 if (req
.readyState
=== 4) {
58 self
.uploadCompleteHandler(req
);
62 req
.open("PUT", this.uploadUrl
);
63 req
.setRequestHeader("Content-Type", file
.type
);
64 req
.setRequestHeader("X-File-Name", file
.name
);
65 addListener(reader
, 'load',
68 req
.sendAsBinary(evt
.target
.result
);
72 reader
.readAsBinaryString(file
);
75 DDFileUploaderBase
.prototype.uploadCompleteHandler = function(req
) {
76 var slide
= this.uploadedSlide
;
77 this.uploadedSlide
.removeChild(slide
.label
);
78 this.uploadedSlide
.removeChild(slide
.progressBar
);
79 var fragment
= getCopyOfNode(req
.responseXML
.documentElement
.firstChild
);
80 var img
= fragment
.getElementsByTagName('img')[0];
81 if (req
.status
=== 200) {
83 var existing
= this.existingSlides
[img
.src
];
85 existing
.src
= existing
.src
+ '?' + Math
.random().toString();
88 slide
.img
.parentNode
.removeChild(slide
.img
);
89 slide
.img
= undefined;
90 slide
.parentNode
.removeChild(slide
);
92 else if(req
.status
=== 201) {
94 img
.onload = function(evt
) {
95 // accelerate GC before replacing
97 slide
.img
.parentNode
.removeChild(slide
.img
);
98 slide
.img
= undefined;
99 slide
.parentNode
.replaceChild(fragment
, slide
);
102 this.previewsLoaded
--;
103 this.previewQueueLoadNext();
104 this.uploadQueueLoadNext();
107 DDFileUploaderBase
.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 // Methods about queue
117 DDFileUploaderBase
.prototype.uploadQueuePush = function(slide
) {
118 this.uploadQueue
.push(slide
);
119 if (!this._uploadQueueRunning
) {
120 this.startUploadQueue();
124 DDFileUploaderBase
.prototype.startUploadQueue = function() {
125 this._uploadQueueRunning
= true;
126 this.uploadQueueLoadNext();
130 DDFileUploaderBase
.prototype.uploadQueueLoadNext = function() {
131 var slide
= this.uploadQueue
.shift();
136 this._uploadQueueRunning
= false;
142 DDFileUploaderBase
.prototype.createSlide = function(file
) {
143 var slide
= document
.createElement('span');
146 var a
= document
.createElement('a');
148 a
.className
= 'slide';
150 var img
= document
.createElement('img');
151 img
.className
= 'hidden';
152 var size
= this.thumbnailSize
;
154 img
.onload = function(evt
) {
155 if (img
.width
> img
.height
) { // landscape
156 img
.height
= Math
.round(size
* img
.height
/ img
.width
);
160 img
.width
= Math
.round(size
* img
.width
/ img
.height
);
163 img
.style
.marginLeft
= Math
.floor((self
.slideSize
- img
.width
) / 2) + 'px';
164 img
.style
.marginTop
= Math
.floor((self
.slideSize
- img
.height
) / 2) + 'px';
165 img
.style
.opacity
= 0.2;
166 img
.className
= undefined;
171 var label
= document
.createElement('span');
173 label
.className
= 'label';
174 label
.innerHTML
= file
.name
;
176 var progressBar
= document
.createElement('span');
177 progressBar
.className
= 'upload-progress';
178 slide
.progressBar
= progressBar
;
180 slide
.appendChild(a
);
181 slide
.appendChild(progressBar
);
182 slide
.appendChild(label
);
183 this.dropbox
.appendChild(slide
);
188 DDFileUploaderBase
.prototype.updateProgressBar = function(progress
) {
189 // 0 <= progress <= 1
190 var size
= this.progressBarMaxSize
* progress
;
191 size
= Math
.round(size
);
192 this.progressBar
.style
.width
= size
+ 'px';
195 DDFileUploaderBase
.prototype.previewUploadedImage = function(slide
) {
196 var reader
= new FileReader();
197 var size
= this.thumbnailSize
;
200 reader
.onload = function(evt
) {
201 slide
.img
.src
= evt
.target
.result
;
202 setTimeout(function(){self
.previewQueueLoadNext();}, 500);
204 reader
.readAsDataURL(slide
.file
);