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('<span style="display:block; position:absolute; background:#ef8e32; height:4px; border-radius:2px; width:0"/>')
50 rel
.append(progressBar
);
51 var link
= new CKEDITOR
.dom
.element('a');
52 link
.setAttribute('href', '#');
53 link
.appendText(file
.name
);
54 container
.append(link
);
58 proxy
.container
= container
;
59 proxy
.progressBar
= progressBar
;
64 // Methods about upload
65 PlinnCKDDUploader
.prototype.handleFiles = function(files
) {
67 for (i
=0 ; i
<files
.length
; i
++) {
69 if (reImage
.test(file
.type
)) {
73 proxy
= this.createFileProxy(file
);
74 this.editor
.insertElement(proxy
.container
);
75 this.uploadQueuePush(proxy
);
82 PlinnCKDDUploader
.prototype.beforeUpload = function(item
) {
83 this.uploadedItem
= item
;
84 this.progressBar
= item
.progressBar
;
85 this.progressBarMaxSize
= item
.container
.getSize('width');
89 PlinnCKDDUploader
.prototype.upload = function(item
) {
90 // item.file must be the file to be uploaded
91 this.beforeUpload(item
);
92 var reader
= new FileReader();
93 var req
= new XMLHttpRequest();
98 addListener(req
.upload
, 'progress', function(evt
){self
.progressHandler(evt
);});
99 addListener(req
, 'readystatechange',
101 if (req
.readyState
=== 4) {
102 self
.uploadCompleteHandler(req
);
106 req
.open("PUT", this.uploadUrl
);
107 req
.setRequestHeader("Content-Type", file
.type
);
108 req
.setRequestHeader("X-File-Name", encodeURI(file
.name
));
109 addListener(reader
, 'load',
112 req
.sendAsBinary(evt
.target
.result
);
116 reader
.readAsBinaryString(file
);
120 PlinnCKDDUploader
.prototype.uploadCompleteHandlerCB = function(req
) {
121 var item
= this.uploadedItem
;
122 var data
= req
.responseXML
.documentElement
;
123 var link
= new CKEDITOR
.dom
.element('a');
124 link
.setAttribute('href', 'attachments/' + data
.getAttribute('id'));
125 link
.appendText(data
.getAttribute('title'));
126 link
.replace(item
.container
);
129 PlinnCKDDUploader
.prototype.uploadCompleteHandler = function(req
) {
130 this.uploadCompleteHandlerCB(req
);
131 this.uploadQueueLoadNext();
134 PlinnCKDDUploader
.prototype.progressHandlerCB = function(progress
) {
135 // 0 <= progress <= 1
136 var size
= this.progressBarMaxSize
* progress
;
137 size
= Math
.round(size
);
138 this.progressBar
.setStyle('width', String(size
) + 'px');
141 PlinnCKDDUploader
.prototype.progressHandler = function(evt
) {
142 if (evt
.lengthComputable
) {
143 var progress
= evt
.loaded
/ evt
.total
;
144 this.progressHandlerCB(progress
);
148 // Methods about queue
149 PlinnCKDDUploader
.prototype.uploadQueuePush = function(item
) {
150 this.uploadQueue
.push(item
);
151 if (!this._uploadQueueRunning
) {
152 this.startUploadQueue();
156 PlinnCKDDUploader
.prototype.startUploadQueue = function() {
157 this._uploadQueueRunning
= true;
158 this.uploadQueueLoadNext();
161 PlinnCKDDUploader
.prototype.uploadQueueLoadNext = function() {
162 var item
= this.uploadQueue
.shift();
167 this._uploadQueueRunning
= false;
171 var reSize
= /getResizedImage\?size=(\d+)_(\d+)$/;
173 function updateImageSizeUrlParameters(img
) {
174 if (reSize
.test(img
.src
)){
175 var matches
= reSize
.exec(img
.src
);
176 var srcWidth
= parseInt(matches
[1], 10);
177 var srcHeight
= parseInt(matches
[2], 10);
179 var imgWidth
= parseInt((img
.style
.width
) ? img
.style
.width
: img
.width
, 10);
180 var imgHeight
= parseInt((img
.style
.height
) ? img
.style
.height
: img
.height
, 10);
182 if ((imgWidth
&& imgHeight
) && srcWidth
!== imgWidth
&& srcHeight
!== imgHeight
) {
183 var newUrl
= img
.getAttribute('src', 2).replace(reSize
, 'getResizedImage?size=' + imgWidth
+ '_' + imgHeight
);
184 img
.width
= imgWidth
;
185 img
.height
= imgHeight
;
191 function openPlinnImageDialog(path
, editor
) {
192 var winOptions
= "location=no,menubar=no,toolbar=no,dependent=yes,dialog=yes,minimizable=no,modal=yes,alwaysRaised=yes" +
199 var win
= open(path
+ 'dialog/plinn_image.html', 'PlinnImageDialog', winOptions
);
200 win
.dialogArguments
= {};
201 win
.dialogArguments
.editor
= editor
;
202 win
.dialogArguments
.pluginPath
= path
;
203 win
.dialogArguments
.CKEDITOR
= CKEDITOR
;
207 CKEDITOR
.plugins
.add( 'plinn_image',
209 init : function( editor
)
211 /* Add listener on getData event to compute images
212 src attributes before saving data.
214 editor
.on('instanceReady', function(){
217 var tmpDiv
= document
.createElement('div');
218 tmpDiv
.innerHTML
= evt
.data
.dataValue
;
219 var images
= tmpDiv
.getElementsByTagName('IMG');
221 for (i
= 0 ; i
< images
.length
; i
++) {
222 updateImageSizeUrlParameters(images
[i
]);}
223 evt
.data
.dataValue
= tmpDiv
.innerHTML
;
226 // drag & drop upload initialisation
227 var dd
= new PlinnCKDDUploader(editor
);
231 var pluginPath
= this.path
;
232 var allowed
= 'img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}';
233 var required
= 'img[alt,src]';
234 var command
= editor
.addCommand('plinn_image',
236 exec : function(editor
){openPlinnImageDialog(pluginPath
, editor
);},
237 allowedContent
: allowed
,
238 requiredContent
: required
242 editor
.ui
.addButton('PlinnImage',
244 label
: editor
.lang
.common
.image
,
245 icon
: pluginPath
+ 'dialog/plinn_image.png',
246 command
: 'plinn_image'