Gestion de deux queues de chargement : en local, et en upload.
[Plinn.git] / skins / fileupload.js
1 // © 2013 Benoît Pin MINES ParisTech
2 var DDFileUploader;
3
4 (function(){
5
6 DDFileUploader = function(dropbox, uploadUrl) {
7 this.dropbox = dropbox;
8 this.uploadUrl = uploadUrl;
9 this.slideSize = 222;
10 this.progressBarMaxSize = 200; // pixels
11 this.thumbnailSize = 180;
12 this.previewQueue = [];
13 this._previewQueueRunning = false;
14 this.uploadQueue = [];
15 this._uploadQueueRunning = false;
16 var self = this;
17 addListener(dropbox, 'dragenter', function(evt){self.dragenter(evt);});
18 addListener(dropbox, 'dragover', function(evt){self.dragover(evt);});
19 addListener(dropbox, 'drop', function(evt){self.drop(evt);});
20 };
21
22 // Drag and drop
23 DDFileUploader.prototype.dragenter = function(evt) {
24 disableDefault(evt);
25 disablePropagation(evt);
26 };
27
28 DDFileUploader.prototype.dragover = function(evt) {
29 disableDefault(evt);
30 disablePropagation(evt);
31 evt = getEventObject(evt);
32 var dt = evt.dataTransfer;
33 dt.dropEffect = 'copy';
34 };
35
36 DDFileUploader.prototype.drop = function(evt) {
37 disableDefault(evt);
38 disablePropagation(evt);
39 getEventObject(evt);
40 var dt = evt.dataTransfer;
41 dt.dropEffect = 'copy';
42 this.handleFiles(dt.files);
43 };
44
45 // Methods about upload
46 DDFileUploader.prototype.handleFiles = function(files) {
47 var file, i, slide;
48 for (i = 0; i < files.length; i++) {
49 file = files[i];
50 slide = this.createSlide(file);
51 this.previewQueuePush(slide);
52 this.uploadQueuePush(slide);
53 // this.previewUploadedImage(file);
54 // this.upload(file);
55 }
56 };
57
58 DDFileUploader.prototype.upload = function(slide) {
59 var reader = new FileReader();
60 var req = new XMLHttpRequest();
61 var file = slide.file;
62 this.previewImg = slide.img;
63 this.progressBar = slide.progressBar;
64 var self = this;
65
66 addListener(req.upload, 'progress', function(evt){self.progressHandler(evt);});
67 addListener(req.upload, 'load', function(evt){self.uploadCompleteHandler(evt);});
68
69 req.open("PUT", this.uploadUrl + '/' + file.name);
70 req.setRequestHeader("Content-Type", file.type);
71 addListener(reader, 'load', function(evt){req.sendAsBinary(evt.target.result);});
72 reader.readAsBinaryString(file);
73 };
74
75 DDFileUploader.prototype.uploadCompleteHandler = function(evt) {
76 this.progressBar.parentNode.removeChild(this.progressBar);
77 this.uploadQueueLoadNext();
78 };
79
80 DDFileUploader.prototype.progressHandler = function(evt) {
81 if (evt.lengthComputable) {
82 var progress = evt.loaded / evt.total;
83 this.updateProgressBar(progress);
84 var currentOpacity = this.previewImg.style.opacity;
85 this.previewImg.style.opacity = Math.max(currentOpacity, progress);
86 }
87 };
88
89 // Method about queues
90
91 DDFileUploader.prototype.previewQueuePush = function(slide) {
92 this.previewQueue.push(slide);
93 if (!this._previewQueueRunning)
94 this.startPreviewQueue();
95 };
96
97 DDFileUploader.prototype.startPreviewQueue = function() {
98 this._previewQueueRunning = true;
99 this.previewQueueLoadNext();
100 };
101
102 DDFileUploader.prototype.previewQueueLoadNext = function() {
103 var slide = this.previewQueue.shift();
104 if (slide)
105 this.previewUploadedImage(slide);
106 else
107 this._previewQueueRunning = false;
108 };
109
110 DDFileUploader.prototype.uploadQueuePush = function(slide) {
111 this.uploadQueue.push(slide);
112 if (!this._uploadQueueRunning)
113 this.startUploadQueue();
114 };
115
116 DDFileUploader.prototype.startUploadQueue = function() {
117 this._uploadQueueRunning = true;
118 this.uploadQueueLoadNext();
119 };
120
121
122 DDFileUploader.prototype.uploadQueueLoadNext = function() {
123 var slide = this.uploadQueue.shift();
124 if (slide)
125 this.upload(slide);
126 else
127 this._uploadQueueRunning = false;
128 };
129
130
131 // User interface
132 DDFileUploader.prototype.createSlide = function(file) {
133 var slide = document.createElement('span');
134 slide.file = file;
135
136 var a = document.createElement('a');
137 a.href = '#';
138 a.className = 'slide';
139
140 var img = document.createElement('img');
141 img.className = 'hidden';
142 var size = this.thumbnailSize;
143 var self = this;
144 img.onload = function(evt) {
145 console.info('createSlide loaded.')
146 if (img.width > img.height) { // landscape
147 img.height = Math.round(size * img.height / img.width);
148 img.width = size;
149 }
150 else {
151 img.width = Math.round(size * img.width / img.height);
152 img.height = size;
153 }
154 img.style.marginLeft = Math.round((self.slideSize - img.width) / 2) + 'px';
155 img.style.marginTop = Math.round((self.slideSize - img.height) / 2) + 'px';
156 img.style.opacity = 0.2;
157 img.className = undefined;
158 };
159 a.appendChild(img);
160 slide.img = img;
161
162 var progressBar = document.createElement('span');
163 progressBar.className = 'upload-progress';
164 slide.progressBar = progressBar;
165
166 slide.appendChild(a);
167 slide.appendChild(progressBar);
168 // this.progressBar = progressBar;
169 this.dropbox.appendChild(slide);
170
171 return slide;
172 };
173
174 DDFileUploader.prototype.updateProgressBar = function(progress) {
175 // 0 <= progress <= 1
176 var size = this.progressBarMaxSize * progress;
177 size = Math.round(size);
178 this.progressBar.style.width = size + 'px';
179 };
180
181 DDFileUploader.prototype.previewUploadedImage = function(slide) {
182 var reader = new FileReader();
183 var size = this.thumbnailSize;
184 var self = this;
185
186 reader.onload = function(evt) {
187 console.info('previewUploadedImage loaded.')
188 slide.img.src = evt.target.result;
189 setTimeout(function(){self.previewQueueLoadNext();}, 1000);
190 // self.previewQueueLoadNext();
191 };
192 reader.readAsDataURL(slide.file);
193 };
194
195 }());