c7ae5ec385739ddf4d40c521439ffb053f0caefe
[ckeditor.git] / skins / ckeditor / plugins / plinn_image / plugin.js
1 /* © 2011 Benoît Pin, MINES ParisTech */
2
3
4 (function(){
5
6 var reImage = /^image\//;
7
8 var PlinnCKDDUploader = function(editor) {
9 this.editor = editor;
10 this.uploadUrl = editor.config.baseHref + 'attachments/put_upload';
11 this.uploadQueue = [];
12 this._uploadQueueRunning = false;
13 var self = this;
14 editor.document.on('dragenter', function(e) {self.dragenter(e);});
15 editor.document.on('dragover', function(e) {self.dragover(e);});
16 editor.document.on('drop', function(e) {self.drop(e);});
17 };
18
19 // Drag and drop
20 PlinnCKDDUploader.prototype.dragenter = function(e) {
21 var evt = e.data.$;
22 disableDefault(evt);
23 disablePropagation(evt);
24 };
25
26 PlinnCKDDUploader.prototype.dragover = function(e) {
27 var evt = e.data.$;
28 disableDefault(evt);
29 disablePropagation(evt);
30 evt = getEventObject(evt);
31 var dt = evt.dataTransfer;
32 dt.dropEffect = 'copy';
33 };
34
35 PlinnCKDDUploader.prototype.drop = function(e) {
36 var evt = e.data.$;
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 PlinnCKDDUploader.prototype.createFileProxy = function(file) {
46 var container = new CKEDITOR.dom.element('span');
47 var rel = CKEDITOR.dom.element.createFromHtml('<span style="position:relative"/>');
48 container.append(rel);
49 var progressBar = CKEDITOR.dom.element.createFromHtml(
50 '<span style="display:block; position:absolute; background:#ef8e32; height:4px; border-radius:2px; width:0; left:0; top:1em"/>');
51 rel.append(progressBar);
52 var link = new CKEDITOR.dom.element('a');
53 link.setAttribute('href', '#');
54 link.appendText(file.name);
55 container.append(link);
56
57 var proxy = {};
58 proxy.file = file;
59 proxy.container = container;
60 proxy.progressBar = progressBar;
61 proxy.link = link;
62 return proxy;
63 };
64
65 // Methods about upload
66 PlinnCKDDUploader.prototype.handleFiles = function(files) {
67 var file, i, proxy;
68 for (i=0 ; i<files.length ; i++) {
69 file = files[i];
70 if (reImage.test(file.type)) {
71 // TODO
72 }
73 else {
74 proxy = this.createFileProxy(file);
75 this.editor.insertElement(proxy.container);
76 this.editor.insertText(' ');
77 this.uploadQueuePush(proxy);
78 }
79 }
80 };
81
82
83
84 PlinnCKDDUploader.prototype.beforeUpload = function(item) {
85 this.uploadedItem = item;
86 this.progressBar = item.progressBar;
87 this.progressBarMaxSize = item.container.getSize('width');
88 };
89
90
91 PlinnCKDDUploader.prototype.upload = function(item) {
92 // item.file must be the file to be uploaded
93 this.beforeUpload(item);
94 var reader = new FileReader();
95 var req = new XMLHttpRequest();
96 var file = item.file;
97
98 var self = this;
99
100 addListener(req.upload, 'progress', function(evt){self.progressHandler(evt);});
101 addListener(req, 'readystatechange',
102 function(evt) {
103 if (req.readyState === 4) {
104 self.uploadCompleteHandler(req);
105 }
106 });
107
108 req.open("PUT", this.uploadUrl);
109 req.setRequestHeader("Content-Type", file.type);
110 req.setRequestHeader("X-File-Name", encodeURI(file.name));
111 addListener(reader, 'load',
112 function(evt){
113 try {
114 req.sendAsBinary(evt.target.result);
115 }
116 catch(e){}
117 });
118 reader.readAsBinaryString(file);
119 };
120
121
122 PlinnCKDDUploader.prototype.uploadCompleteHandlerCB = function(req) {
123 var item = this.uploadedItem;
124 var data = req.responseXML.documentElement;
125 var link = new CKEDITOR.dom.element('a');
126 link.setAttribute('href', 'attachments/' + data.getAttribute('id'));
127 link.appendText(data.getAttribute('title'));
128 link.replace(item.container);
129 };
130
131 PlinnCKDDUploader.prototype.uploadCompleteHandler = function(req) {
132 this.uploadCompleteHandlerCB(req);
133 this.uploadQueueLoadNext();
134 };
135
136 PlinnCKDDUploader.prototype.progressHandlerCB = function(progress) {
137 // 0 <= progress <= 1
138 var size = this.progressBarMaxSize * progress;
139 size = Math.round(size);
140 this.progressBar.setStyle('width', String(size) + 'px');
141 };
142
143 PlinnCKDDUploader.prototype.progressHandler = function(evt) {
144 if (evt.lengthComputable) {
145 var progress = evt.loaded / evt.total;
146 this.progressHandlerCB(progress);
147 }
148 };
149
150 // Methods about queue
151 PlinnCKDDUploader.prototype.uploadQueuePush = function(item) {
152 this.uploadQueue.push(item);
153 if (!this._uploadQueueRunning) {
154 this.startUploadQueue();
155 }
156 };
157
158 PlinnCKDDUploader.prototype.startUploadQueue = function() {
159 this._uploadQueueRunning = true;
160 this.uploadQueueLoadNext();
161 };
162
163 PlinnCKDDUploader.prototype.uploadQueueLoadNext = function() {
164 var item = this.uploadQueue.shift();
165 if (item) {
166 this.upload(item);
167 }
168 else {
169 this._uploadQueueRunning = false;
170 }
171 };
172
173 var reSize = /getResizedImage\?size=(\d+)_(\d+)$/;
174
175 function updateImageSizeUrlParameters(img) {
176 if (reSize.test(img.src)){
177 var matches = reSize.exec(img.src);
178 var srcWidth = parseInt(matches[1], 10);
179 var srcHeight = parseInt(matches[2], 10);
180
181 var imgWidth = parseInt((img.style.width) ? img.style.width : img.width, 10);
182 var imgHeight = parseInt((img.style.height) ? img.style.height : img.height, 10);
183
184 if ((imgWidth && imgHeight) && srcWidth !== imgWidth && srcHeight !== imgHeight) {
185 var newUrl = img.getAttribute('src', 2).replace(reSize, 'getResizedImage?size=' + imgWidth + '_' + imgHeight);
186 img.width = imgWidth;
187 img.height = imgHeight;
188 img.src = newUrl;
189 }
190 }
191 }
192
193 function openPlinnImageDialog(path, editor) {
194 var winOptions = "location=no,menubar=no,toolbar=no,dependent=yes,dialog=yes,minimizable=no,modal=yes,alwaysRaised=yes" +
195 ",resizable=yes" +
196 ",width=801" +
197 ",height=600";
198 //",top=" + iTop +
199 //",left=" + iLeft ;
200
201 var win = open(path + 'dialog/plinn_image.html', 'PlinnImageDialog', winOptions);
202 win.dialogArguments = {};
203 win.dialogArguments.editor = editor;
204 win.dialogArguments.pluginPath = path;
205 win.dialogArguments.CKEDITOR = CKEDITOR;
206 }
207
208
209 CKEDITOR.plugins.add( 'plinn_image',
210 {
211 init : function( editor )
212 {
213 /* Add listener on getData event to compute images
214 src attributes before saving data.
215 */
216 editor.on('instanceReady', function(){
217 editor.on('getData',
218 function(evt) {
219 var tmpDiv = document.createElement('div');
220 tmpDiv.innerHTML = evt.data.dataValue;
221 var images = tmpDiv.getElementsByTagName('IMG');
222 var i;
223 for (i = 0 ; i < images.length ; i++) {
224 updateImageSizeUrlParameters(images[i]);}
225 evt.data.dataValue = tmpDiv.innerHTML;
226 }
227 );
228 // drag & drop upload initialisation
229 var dd = new PlinnCKDDUploader(editor);
230 });
231
232
233 var pluginPath = this.path;
234 var allowed = 'img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}';
235 var required = 'img[alt,src]';
236 var command = editor.addCommand('plinn_image',
237 {
238 exec : function(editor){openPlinnImageDialog(pluginPath, editor);},
239 allowedContent: allowed,
240 requiredContent: required
241 }
242 );
243
244 editor.ui.addButton('PlinnImage',
245 {
246 label : editor.lang.common.image,
247 icon : pluginPath + 'dialog/plinn_image.png',
248 command : 'plinn_image'
249 });
250 }
251
252 });
253
254 }());