318f0597fe5def34d3a1871e1a2d5443a1ad45e5
[Plinn.git] / skins / fileupload.js
1 // © 2013 Benoît Pin MINES ParisTech
2 var DDFileUploaderBase;
3
4 (function(){
5
6 DDFileUploaderBase = function(dropbox, uploadUrl) {
7 this.dropbox = dropbox;
8 this.uploadUrl = uploadUrl;
9 this.uploadQueue = [];
10 this._uploadQueueRunning = false;
11 var self = this;
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);});
15 };
16
17 // Drag and drop
18 DDFileUploaderBase.prototype.dragenter = function(evt) {
19 disableDefault(evt);
20 disablePropagation(evt);
21 };
22
23 DDFileUploaderBase.prototype.dragover = function(evt) {
24 disableDefault(evt);
25 disablePropagation(evt);
26 evt = getEventObject(evt);
27 var dt = evt.dataTransfer;
28 dt.dropEffect = 'copy';
29 };
30
31 DDFileUploaderBase.prototype.drop = function(evt) {
32 disableDefault(evt);
33 disablePropagation(evt);
34 getEventObject(evt);
35 var dt = evt.dataTransfer;
36 dt.dropEffect = 'copy';
37 this.handleFiles(dt.files);
38 };
39
40 // Methods about upload
41 DDFileUploaderBase.prototype.handleFiles = function(files) {
42 // To be implemented by descendant.
43 };
44
45
46
47 DDFileUploaderBase.prototype.beforeUpload = function(item) {
48 // To be implemented by decendant.
49 };
50
51
52 DDFileUploaderBase.prototype.upload = function(item) {
53 // item.file must be the file to be uploaded
54 this.beforeUpload(item);
55 var reader = new FileReader();
56 var req = new XMLHttpRequest();
57 var file = item.file;
58
59 var self = this;
60
61 addListener(req.upload, 'progress', function(evt){self.progressHandler(evt);});
62 addListener(req, 'readystatechange',
63 function(evt) {
64 if (req.readyState === 4) {
65 self.uploadCompleteHandler(req);
66 }
67 });
68
69 req.open("PUT", this.uploadUrl);
70 req.setRequestHeader("Content-Type", file.type);
71 req.setRequestHeader("X-File-Name", file.name);
72 addListener(reader, 'load',
73 function(evt){
74 try {
75 req.sendAsBinary(evt.target.result);
76 }
77 catch(e){}
78 });
79 reader.readAsBinaryString(file);
80 };
81
82 DDFileUploaderBase.prototype.uploadCompleteHandler = function(req) {
83 var slide = this.uploadedSlide;
84 this.uploadedSlide.removeChild(slide.label);
85 this.uploadedSlide.removeChild(slide.progressBar);
86 var fragment = getCopyOfNode(req.responseXML.documentElement.firstChild);
87 var img = fragment.getElementsByTagName('img')[0];
88 if (req.status === 200) {
89 // update
90 var existing = this.existingSlides[img.src];
91 if (existing) {
92 existing.src = existing.src + '?' + Math.random().toString();
93 }
94 slide.img.src = '';
95 slide.img.parentNode.removeChild(slide.img);
96 slide.img = undefined;
97 slide.parentNode.removeChild(slide);
98 }
99 else if(req.status === 201) {
100 // creation
101 img.onload = function(evt) {
102 // accelerate GC before replacing
103 slide.img.src = '';
104 slide.img.parentNode.removeChild(slide.img);
105 slide.img = undefined;
106 slide.parentNode.replaceChild(fragment, slide);
107 };
108 }
109 this.previewsLoaded--;
110 this.previewQueueLoadNext();
111 this.uploadQueueLoadNext();
112 };
113
114 DDFileUploaderBase.prototype.progressHandlerCB = function(progress) {
115 // To be implemented by descendant.
116 // 0 <= progress <= 1
117 };
118
119 DDFileUploaderBase.prototype.progressHandler = function(evt) {
120 if (evt.lengthComputable) {
121 var progress = evt.loaded / evt.total;
122 this.progressHandlerCB(progress);
123 }
124 };
125
126 // Methods about queue
127 DDFileUploaderBase.prototype.uploadQueuePush = function(item) {
128 this.uploadQueue.push(item);
129 if (!this._uploadQueueRunning) {
130 this.startUploadQueue();
131 }
132 };
133
134 DDFileUploaderBase.prototype.startUploadQueue = function() {
135 this._uploadQueueRunning = true;
136 this.uploadQueueLoadNext();
137 };
138
139 DDFileUploaderBase.prototype.uploadQueueLoadNext = function() {
140 var item = this.uploadQueue.shift();
141 if (item) {
142 this.upload(item);
143 }
144 else {
145 this._uploadQueueRunning = false;
146 }
147 };
148
149 }());