1 /* © 2011 Benoît Pin, MINES ParisTech */
6 var reImage
= /^image\//;
8 var PlinnCKDDUploader = function(editor
) {
10 this.uploadUrl
= editor
.config
.baseHref
+ 'attachments/put_upload';
11 this.uploadQueue
= [];
12 this._uploadQueueRunning
= false;
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
);});
20 PlinnCKDDUploader
.prototype.dragenter = function(e
) {
23 disablePropagation(evt
);
26 PlinnCKDDUploader
.prototype.dragover = function(e
) {
29 disablePropagation(evt
);
30 evt
= getEventObject(evt
);
31 var dt
= evt
.dataTransfer
;
32 dt
.dropEffect
= 'copy';
35 PlinnCKDDUploader
.prototype.drop = function(e
) {
38 disablePropagation(evt
);
40 var dt
= evt
.dataTransfer
;
41 dt
.dropEffect
= 'copy';
42 this.handleFiles(dt
.files
);
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
.setStyle('opacity', 0.2);
55 link
.appendText(file
.name
);
56 container
.append(link
);
60 proxy
.container
= container
;
61 proxy
.progressBar
= progressBar
;
66 // Methods about upload
67 PlinnCKDDUploader
.prototype.handleFiles = function(files
) {
69 for (i
=0 ; i
<files
.length
; i
++) {
71 if (reImage
.test(file
.type
)) {
75 proxy
= this.createFileProxy(file
);
76 this.editor
.insertElement(proxy
.container
);
77 this.editor
.insertText(' ');
78 this.uploadQueuePush(proxy
);
85 PlinnCKDDUploader
.prototype.beforeUpload = function(item
) {
86 this.uploadedItem
= item
;
87 this.progressBar
= item
.progressBar
;
88 this.progressBarMaxSize
= item
.container
.getSize('width');
92 PlinnCKDDUploader
.prototype.upload = function(item
) {
93 // item.file must be the file to be uploaded
94 this.beforeUpload(item
);
95 var reader
= new FileReader();
96 var req
= new XMLHttpRequest();
101 addListener(req
.upload
, 'progress', function(evt
){self
.progressHandler(evt
);});
102 addListener(req
, 'readystatechange',
104 if (req
.readyState
=== 4) {
105 self
.uploadCompleteHandler(req
);
109 req
.open("PUT", this.uploadUrl
);
110 req
.setRequestHeader("Content-Type", file
.type
);
111 req
.setRequestHeader("X-File-Name", encodeURI(file
.name
));
112 addListener(reader
, 'load',
115 req
.sendAsBinary(evt
.target
.result
);
119 reader
.readAsBinaryString(file
);
123 PlinnCKDDUploader
.prototype.uploadCompleteHandlerCB = function(req
) {
124 var item
= this.uploadedItem
;
125 var data
= req
.responseXML
.documentElement
;
126 var link
= new CKEDITOR
.dom
.element('a');
127 link
.setAttribute('href', 'attachments/' + data
.getAttribute('id'));
128 link
.appendText(data
.getAttribute('title'));
129 link
.replace(item
.container
);
132 PlinnCKDDUploader
.prototype.uploadCompleteHandler = function(req
) {
133 this.uploadCompleteHandlerCB(req
);
134 this.uploadQueueLoadNext();
137 PlinnCKDDUploader
.prototype.progressHandlerCB = function(progress
) {
138 // 0 <= progress <= 1
139 var size
= this.progressBarMaxSize
* progress
;
140 size
= Math
.round(size
);
141 this.progressBar
.setStyle('width', String(size
) + 'px');
142 var currentOpacity
= this.uploadedItem
.link
.getStyle('opacity');
143 this.uploadedItem
.link
.setStyle('opacity', Math
.max(currentOpacity
, progress
));
146 PlinnCKDDUploader
.prototype.progressHandler = function(evt
) {
147 if (evt
.lengthComputable
) {
148 var progress
= evt
.loaded
/ evt
.total
;
149 this.progressHandlerCB(progress
);
153 // Methods about queue
154 PlinnCKDDUploader
.prototype.uploadQueuePush = function(item
) {
155 this.uploadQueue
.push(item
);
156 if (!this._uploadQueueRunning
) {
157 this.startUploadQueue();
161 PlinnCKDDUploader
.prototype.startUploadQueue = function() {
162 this._uploadQueueRunning
= true;
163 this.uploadQueueLoadNext();
166 PlinnCKDDUploader
.prototype.uploadQueueLoadNext = function() {
167 var item
= this.uploadQueue
.shift();
172 this._uploadQueueRunning
= false;
176 var reSize
= /getResizedImage\?size=(\d+)_(\d+)$/;
178 function updateImageSizeUrlParameters(img
) {
179 if (reSize
.test(img
.src
)){
180 var matches
= reSize
.exec(img
.src
);
181 var srcWidth
= parseInt(matches
[1], 10);
182 var srcHeight
= parseInt(matches
[2], 10);
184 var imgWidth
= parseInt((img
.style
.width
) ? img
.style
.width
: img
.width
, 10);
185 var imgHeight
= parseInt((img
.style
.height
) ? img
.style
.height
: img
.height
, 10);
187 if ((imgWidth
&& imgHeight
) && srcWidth
!== imgWidth
&& srcHeight
!== imgHeight
) {
188 var newUrl
= img
.getAttribute('src', 2).replace(reSize
, 'getResizedImage?size=' + imgWidth
+ '_' + imgHeight
);
189 img
.width
= imgWidth
;
190 img
.height
= imgHeight
;
196 function openPlinnImageDialog(path
, editor
) {
197 var winOptions
= "location=no,menubar=no,toolbar=no,dependent=yes,dialog=yes,minimizable=no,modal=yes,alwaysRaised=yes" +
204 var win
= open(path
+ 'dialog/plinn_image.html', 'PlinnImageDialog', winOptions
);
205 win
.dialogArguments
= {};
206 win
.dialogArguments
.editor
= editor
;
207 win
.dialogArguments
.pluginPath
= path
;
208 win
.dialogArguments
.CKEDITOR
= CKEDITOR
;
212 CKEDITOR
.plugins
.add( 'plinn_image',
214 init : function( editor
)
216 /* Add listener on getData event to compute images
217 src attributes before saving data.
219 editor
.on('instanceReady', function(){
222 var tmpDiv
= document
.createElement('div');
223 tmpDiv
.innerHTML
= evt
.data
.dataValue
;
224 var images
= tmpDiv
.getElementsByTagName('IMG');
226 for (i
= 0 ; i
< images
.length
; i
++) {
227 updateImageSizeUrlParameters(images
[i
]);}
228 evt
.data
.dataValue
= tmpDiv
.innerHTML
;
231 // drag & drop upload initialisation
232 var dd
= new PlinnCKDDUploader(editor
);
236 var pluginPath
= this.path
;
237 var allowed
= 'img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}';
238 var required
= 'img[alt,src]';
239 var command
= editor
.addCommand('plinn_image',
241 exec : function(editor
){openPlinnImageDialog(pluginPath
, editor
);},
242 allowedContent
: allowed
,
243 requiredContent
: required
247 editor
.ui
.addButton('PlinnImage',
249 label
: editor
.lang
.common
.image
,
250 icon
: pluginPath
+ 'dialog/plinn_image.png',
251 command
: 'plinn_image'