]> git.immae.eu Git - perso/Immae/Projets/packagist/piedsjaloux-ckeditor-component.git/blob - sources/plugins/filebrowser/plugin.js
Initial commit
[perso/Immae/Projets/packagist/piedsjaloux-ckeditor-component.git] / sources / plugins / filebrowser / plugin.js
1 /**
2 * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6 /**
7 * @fileOverview The "filebrowser" plugin that adds support for file uploads and
8 * browsing.
9 *
10 * When a file is uploaded or selected inside the file browser, its URL is
11 * inserted automatically into a field defined in the <code>filebrowser</code>
12 * attribute. In order to specify a field that should be updated, pass the tab ID and
13 * the element ID, separated with a colon.<br /><br />
14 *
15 * <strong>Example 1: (Browse)</strong>
16 *
17 * <pre>
18 * {
19 * type : 'button',
20 * id : 'browse',
21 * filebrowser : 'tabId:elementId',
22 * label : editor.lang.common.browseServer
23 * }
24 * </pre>
25 *
26 * If you set the <code>filebrowser</code> attribute for an element other than
27 * the <code>fileButton</code>, the <code>Browse</code> action will be triggered.<br /><br />
28 *
29 * <strong>Example 2: (Quick Upload)</strong>
30 *
31 * <pre>
32 * {
33 * type : 'fileButton',
34 * id : 'uploadButton',
35 * filebrowser : 'tabId:elementId',
36 * label : editor.lang.common.uploadSubmit,
37 * 'for' : [ 'upload', 'upload' ]
38 * }
39 * </pre>
40 *
41 * If you set the <code>filebrowser</code> attribute for a <code>fileButton</code>
42 * element, the <code>QuickUpload</code> action will be executed.<br /><br />
43 *
44 * The filebrowser plugin also supports more advanced configuration performed through
45 * a JavaScript object.
46 *
47 * The following settings are supported:
48 *
49 * <ul>
50 * <li><code>action</code> &ndash; <code>Browse</code> or <code>QuickUpload</code>.</li>
51 * <li><code>target</code> &ndash; the field to update in the <code><em>tabId:elementId</em></code> format.</li>
52 * <li><code>params</code> &ndash; additional arguments to be passed to the server connector (optional).</li>
53 * <li><code>onSelect</code> &ndash; a function to execute when the file is selected/uploaded (optional).</li>
54 * <li><code>url</code> &ndash; the URL to be called (optional).</li>
55 * </ul>
56 *
57 * <strong>Example 3: (Quick Upload)</strong>
58 *
59 * <pre>
60 * {
61 * type : 'fileButton',
62 * label : editor.lang.common.uploadSubmit,
63 * id : 'buttonId',
64 * filebrowser :
65 * {
66 * action : 'QuickUpload', // required
67 * target : 'tab1:elementId', // required
68 * params : // optional
69 * {
70 * type : 'Files',
71 * currentFolder : '/folder/'
72 * },
73 * onSelect : function( fileUrl, errorMessage ) // optional
74 * {
75 * // Do not call the built-in selectFuntion.
76 * // return false;
77 * }
78 * },
79 * 'for' : [ 'tab1', 'myFile' ]
80 * }
81 * </pre>
82 *
83 * Suppose you have a file element with an ID of <code>myFile</code>, a text
84 * field with an ID of <code>elementId</code> and a <code>fileButton</code>.
85 * If the <code>filebowser.url</code> attribute is not specified explicitly,
86 * the form action will be set to <code>filebrowser[<em>DialogWindowName</em>]UploadUrl</code>
87 * or, if not specified, to <code>filebrowserUploadUrl</code>. Additional parameters
88 * from the <code>params</code> object will be added to the query string. It is
89 * possible to create your own <code>uploadHandler</code> and cancel the built-in
90 * <code>updateTargetElement</code> command.<br /><br />
91 *
92 * <strong>Example 4: (Browse)</strong>
93 *
94 * <pre>
95 * {
96 * type : 'button',
97 * id : 'buttonId',
98 * label : editor.lang.common.browseServer,
99 * filebrowser :
100 * {
101 * action : 'Browse',
102 * url : '/ckfinder/ckfinder.html&amp;type=Images',
103 * target : 'tab1:elementId'
104 * }
105 * }
106 * </pre>
107 *
108 * In this example, when the button is pressed, the file browser will be opened in a
109 * popup window. If you do not specify the <code>filebrowser.url</code> attribute,
110 * <code>filebrowser[<em>DialogName</em>]BrowseUrl</code> or
111 * <code>filebrowserBrowseUrl</code> will be used. After selecting a file in the file
112 * browser, an element with an ID of <code>elementId</code> will be updated. Just
113 * like in the third example, a custom <code>onSelect</code> function may be defined.
114 */
115
116 ( function() {
117 // Default input element name for CSRF protection token.
118 var TOKEN_INPUT_NAME = 'ckCsrfToken';
119
120 // Adds (additional) arguments to given url.
121 //
122 // @param {String}
123 // url The url.
124 // @param {Object}
125 // params Additional parameters.
126 function addQueryString( url, params ) {
127 var queryString = [];
128
129 if ( !params )
130 return url;
131 else {
132 for ( var i in params )
133 queryString.push( i + '=' + encodeURIComponent( params[ i ] ) );
134 }
135
136 return url + ( ( url.indexOf( '?' ) != -1 ) ? '&' : '?' ) + queryString.join( '&' );
137 }
138
139 // Make a string's first character uppercase.
140 //
141 // @param {String}
142 // str String.
143 function ucFirst( str ) {
144 str += '';
145 var f = str.charAt( 0 ).toUpperCase();
146 return f + str.substr( 1 );
147 }
148
149 // The onlick function assigned to the 'Browse Server' button. Opens the
150 // file browser and updates target field when file is selected.
151 //
152 // @param {CKEDITOR.event}
153 // evt The event object.
154 function browseServer() {
155 var dialog = this.getDialog();
156 var editor = dialog.getParentEditor();
157
158 editor._.filebrowserSe = this;
159
160 var width = editor.config[ 'filebrowser' + ucFirst( dialog.getName() ) + 'WindowWidth' ] || editor.config.filebrowserWindowWidth || '80%';
161 var height = editor.config[ 'filebrowser' + ucFirst( dialog.getName() ) + 'WindowHeight' ] || editor.config.filebrowserWindowHeight || '70%';
162
163 var params = this.filebrowser.params || {};
164 params.CKEditor = editor.name;
165 params.CKEditorFuncNum = editor._.filebrowserFn;
166 if ( !params.langCode )
167 params.langCode = editor.langCode;
168
169 var url = addQueryString( this.filebrowser.url, params );
170 // TODO: V4: Remove backward compatibility (#8163).
171 editor.popup( url, width, height, editor.config.filebrowserWindowFeatures || editor.config.fileBrowserWindowFeatures );
172 }
173
174 // Appends token preventing CSRF attacks to the form of provided file input.
175 //
176 // @since 4.5.6
177 // @param {CKEDITOR.dom.element} fileInput
178 function appendToken( fileInput ) {
179 var tokenElement;
180 var form = new CKEDITOR.dom.element( fileInput.$.form );
181
182 if ( form ) {
183 // Check if token input element already exists.
184 tokenElement = form.$.elements[ TOKEN_INPUT_NAME ];
185
186 // Create new if needed.
187 if ( !tokenElement ) {
188 tokenElement = new CKEDITOR.dom.element( 'input' );
189 tokenElement.setAttributes( {
190 name: TOKEN_INPUT_NAME,
191 type: 'hidden'
192 } );
193
194 form.append( tokenElement );
195 } else {
196 tokenElement = new CKEDITOR.dom.element( tokenElement );
197 }
198
199 tokenElement.setAttribute( 'value', CKEDITOR.tools.getCsrfToken() );
200 }
201 }
202
203 // The onlick function assigned to the 'Upload' button. Makes the final
204 // decision whether form is really submitted and updates target field when
205 // file is uploaded.
206 //
207 // @param {CKEDITOR.event}
208 // evt The event object.
209 function uploadFile() {
210 var dialog = this.getDialog();
211 var editor = dialog.getParentEditor();
212
213 editor._.filebrowserSe = this;
214
215 // If user didn't select the file, stop the upload.
216 if ( !dialog.getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getInputElement().$.value )
217 return false;
218
219 if ( !dialog.getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getAction() )
220 return false;
221
222 return true;
223 }
224
225 // Setups the file element.
226 //
227 // @param {CKEDITOR.ui.dialog.file}
228 // fileInput The file element used during file upload.
229 // @param {Object}
230 // filebrowser Object containing filebrowser settings assigned to
231 // the fileButton associated with this file element.
232 function setupFileElement( editor, fileInput, filebrowser ) {
233 var params = filebrowser.params || {};
234 params.CKEditor = editor.name;
235 params.CKEditorFuncNum = editor._.filebrowserFn;
236 if ( !params.langCode )
237 params.langCode = editor.langCode;
238
239 fileInput.action = addQueryString( filebrowser.url, params );
240 fileInput.filebrowser = filebrowser;
241 }
242
243 // Traverse through the content definition and attach filebrowser to
244 // elements with 'filebrowser' attribute.
245 //
246 // @param String
247 // dialogName Dialog name.
248 // @param {CKEDITOR.dialog.definitionObject}
249 // definition Dialog definition.
250 // @param {Array}
251 // elements Array of {@link CKEDITOR.dialog.definition.content}
252 // objects.
253 function attachFileBrowser( editor, dialogName, definition, elements ) {
254 if ( !elements || !elements.length )
255 return;
256
257 var element;
258
259 for ( var i = elements.length; i--; ) {
260 element = elements[ i ];
261
262 if ( element.type == 'hbox' || element.type == 'vbox' || element.type == 'fieldset' )
263 attachFileBrowser( editor, dialogName, definition, element.children );
264
265 if ( !element.filebrowser )
266 continue;
267
268 if ( typeof element.filebrowser == 'string' ) {
269 var fb = {
270 action: ( element.type == 'fileButton' ) ? 'QuickUpload' : 'Browse',
271 target: element.filebrowser
272 };
273 element.filebrowser = fb;
274 }
275
276 if ( element.filebrowser.action == 'Browse' ) {
277 var url = element.filebrowser.url;
278 if ( url === undefined ) {
279 url = editor.config[ 'filebrowser' + ucFirst( dialogName ) + 'BrowseUrl' ];
280 if ( url === undefined )
281 url = editor.config.filebrowserBrowseUrl;
282 }
283
284 if ( url ) {
285 element.onClick = browseServer;
286 element.filebrowser.url = url;
287 element.hidden = false;
288 }
289 } else if ( element.filebrowser.action == 'QuickUpload' && element[ 'for' ] ) {
290 url = element.filebrowser.url;
291 if ( url === undefined ) {
292 url = editor.config[ 'filebrowser' + ucFirst( dialogName ) + 'UploadUrl' ];
293 if ( url === undefined )
294 url = editor.config.filebrowserUploadUrl;
295 }
296
297 if ( url ) {
298 var onClick = element.onClick;
299 element.onClick = function( evt ) {
300 // "element" here means the definition object, so we need to find the correct
301 // button to scope the event call
302 var sender = evt.sender;
303 if ( onClick && onClick.call( sender, evt ) === false )
304 return false;
305
306 if ( uploadFile.call( sender, evt ) ) {
307 var fileInput = sender.getDialog().getContentElement( this[ 'for' ][ 0 ], this[ 'for' ][ 1 ] ).getInputElement();
308
309 // Append token preventing CSRF attacks.
310 appendToken( fileInput );
311 return true;
312 }
313
314
315 return false;
316 };
317
318 element.filebrowser.url = url;
319 element.hidden = false;
320 setupFileElement( editor, definition.getContents( element[ 'for' ][ 0 ] ).get( element[ 'for' ][ 1 ] ), element.filebrowser );
321 }
322 }
323 }
324 }
325
326 // Updates the target element with the url of uploaded/selected file.
327 //
328 // @param {String}
329 // url The url of a file.
330 function updateTargetElement( url, sourceElement ) {
331 var dialog = sourceElement.getDialog();
332 var targetElement = sourceElement.filebrowser.target || null;
333
334 // If there is a reference to targetElement, update it.
335 if ( targetElement ) {
336 var target = targetElement.split( ':' );
337 var element = dialog.getContentElement( target[ 0 ], target[ 1 ] );
338 if ( element ) {
339 element.setValue( url );
340 dialog.selectPage( target[ 0 ] );
341 }
342 }
343 }
344
345 // Returns true if filebrowser is configured in one of the elements.
346 //
347 // @param {CKEDITOR.dialog.definitionObject}
348 // definition Dialog definition.
349 // @param String
350 // tabId The tab id where element(s) can be found.
351 // @param String
352 // elementId The element id (or ids, separated with a semicolon) to check.
353 function isConfigured( definition, tabId, elementId ) {
354 if ( elementId.indexOf( ';' ) !== -1 ) {
355 var ids = elementId.split( ';' );
356 for ( var i = 0; i < ids.length; i++ ) {
357 if ( isConfigured( definition, tabId, ids[ i ] ) )
358 return true;
359 }
360 return false;
361 }
362
363 var elementFileBrowser = definition.getContents( tabId ).get( elementId ).filebrowser;
364 return ( elementFileBrowser && elementFileBrowser.url );
365 }
366
367 function setUrl( fileUrl, data ) {
368 var dialog = this._.filebrowserSe.getDialog(),
369 targetInput = this._.filebrowserSe[ 'for' ],
370 onSelect = this._.filebrowserSe.filebrowser.onSelect;
371
372 if ( targetInput )
373 dialog.getContentElement( targetInput[ 0 ], targetInput[ 1 ] ).reset();
374
375 if ( typeof data == 'function' && data.call( this._.filebrowserSe ) === false )
376 return;
377
378 if ( onSelect && onSelect.call( this._.filebrowserSe, fileUrl, data ) === false )
379 return;
380
381 // The "data" argument may be used to pass the error message to the editor.
382 if ( typeof data == 'string' && data )
383 alert( data ); // jshint ignore:line
384
385 if ( fileUrl )
386 updateTargetElement( fileUrl, this._.filebrowserSe );
387 }
388
389 CKEDITOR.plugins.add( 'filebrowser', {
390 requires: 'popup',
391 init: function( editor ) {
392 editor._.filebrowserFn = CKEDITOR.tools.addFunction( setUrl, editor );
393 editor.on( 'destroy', function() {
394 CKEDITOR.tools.removeFunction( this._.filebrowserFn );
395 } );
396 }
397 } );
398
399 CKEDITOR.on( 'dialogDefinition', function( evt ) {
400 // We require filebrowser plugin to be loaded.
401 if ( !evt.editor.plugins.filebrowser )
402 return;
403
404 var definition = evt.data.definition,
405 element;
406 // Associate filebrowser to elements with 'filebrowser' attribute.
407 for ( var i = 0; i < definition.contents.length; ++i ) {
408 if ( ( element = definition.contents[ i ] ) ) {
409 attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
410 if ( element.hidden && element.filebrowser )
411 element.hidden = !isConfigured( definition, element.id, element.filebrowser );
412
413 }
414 }
415 } );
416
417 } )();
418
419 /**
420 * The location of an external file manager that should be launched when the **Browse Server**
421 * button is pressed. If configured, the **Browse Server** button will appear in the
422 * **Link**, **Image**, and **Flash** dialog windows.
423 *
424 * Read more in the [documentation](#!/guide/dev_file_browse_upload)
425 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
426 *
427 * config.filebrowserBrowseUrl = '/browser/browse.php';
428 *
429 * @since 3.0
430 * @cfg {String} [filebrowserBrowseUrl='' (empty string = disabled)]
431 * @member CKEDITOR.config
432 */
433
434 /**
435 * The location of the script that handles file uploads.
436 * If set, the **Upload** tab will appear in the **Link**, **Image**,
437 * and **Flash** dialog windows.
438 *
439 * Read more in the [documentation](#!/guide/dev_file_browse_upload)
440 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
441 *
442 * config.filebrowserUploadUrl = '/uploader/upload.php';
443 *
444 * **Note:** This is a configuration setting for a [file browser/uploader](#!/guide/dev_file_browse_upload).
445 * To configure [uploading dropped or pasted files](#!/guide/dev_file_upload) use the {@link CKEDITOR.config#uploadUrl}
446 * configuration option.
447 *
448 * @since 3.0
449 * @cfg {String} [filebrowserUploadUrl='' (empty string = disabled)]
450 * @member CKEDITOR.config
451 */
452
453 /**
454 * The location of an external file manager that should be launched when the **Browse Server**
455 * button is pressed in the **Image** dialog window.
456 *
457 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
458 *
459 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
460 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
461 *
462 * config.filebrowserImageBrowseUrl = '/browser/browse.php?type=Images';
463 *
464 * @since 3.0
465 * @cfg {String} [filebrowserImageBrowseUrl='' (empty string = disabled)]
466 * @member CKEDITOR.config
467 */
468
469 /**
470 * The location of an external file browser that should be launched when the **Browse Server**
471 * button is pressed in the **Flash** dialog window.
472 *
473 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
474 *
475 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
476 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
477 *
478 * config.filebrowserFlashBrowseUrl = '/browser/browse.php?type=Flash';
479 *
480 * @since 3.0
481 * @cfg {String} [filebrowserFlashBrowseUrl='' (empty string = disabled)]
482 * @member CKEDITOR.config
483 */
484
485 /**
486 * The location of the script that handles file uploads in the **Image** dialog window.
487 *
488 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserUploadUrl}.
489 *
490 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
491 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
492 *
493 * config.filebrowserImageUploadUrl = '/uploader/upload.php?type=Images';
494 *
495 * **Note:** This is a configuration setting for a [file browser/uploader](#!/guide/dev_file_browse_upload).
496 * To configure [uploading dropped or pasted files](#!/guide/dev_file_upload) use the {@link CKEDITOR.config#uploadUrl}
497 * or {@link CKEDITOR.config#imageUploadUrl} configuration option.
498 *
499 * @since 3.0
500 * @cfg {String} [filebrowserImageUploadUrl='' (empty string = disabled)]
501 * @member CKEDITOR.config
502 */
503
504 /**
505 * The location of the script that handles file uploads in the **Flash** dialog window.
506 *
507 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserUploadUrl}.
508 *
509 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
510 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
511 *
512 * config.filebrowserFlashUploadUrl = '/uploader/upload.php?type=Flash';
513 *
514 * @since 3.0
515 * @cfg {String} filebrowserFlashUploadUrl='' (empty string = disabled)]
516 * @member CKEDITOR.config
517 */
518
519 /**
520 * The location of an external file manager that should be launched when the **Browse Server**
521 * button is pressed in the **Link** tab of the **Image** dialog window.
522 *
523 * If not set, CKEditor will use {@link CKEDITOR.config#filebrowserBrowseUrl}.
524 *
525 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-adding-file-manager-scripts-for-selected-dialog-windows)
526 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
527 *
528 * config.filebrowserImageBrowseLinkUrl = '/browser/browse.php';
529 *
530 * @since 3.2
531 * @cfg {String} [filebrowserImageBrowseLinkUrl='' (empty string = disabled)]
532 * @member CKEDITOR.config
533 */
534
535 /**
536 * The features to use in the file manager popup window.
537 *
538 * config.filebrowserWindowFeatures = 'resizable=yes,scrollbars=no';
539 *
540 * @since 3.4.1
541 * @cfg {String} [filebrowserWindowFeatures='location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes']
542 * @member CKEDITOR.config
543 */
544
545 /**
546 * The width of the file manager popup window. It can be a number denoting a value in
547 * pixels or a percent string.
548 *
549 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-file-manager-window-size)
550 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
551 *
552 * config.filebrowserWindowWidth = 750;
553 *
554 * config.filebrowserWindowWidth = '50%';
555 *
556 * @cfg {Number/String} [filebrowserWindowWidth='80%']
557 * @member CKEDITOR.config
558 */
559
560 /**
561 * The height of the file manager popup window. It can be a number denoting a value in
562 * pixels or a percent string.
563 *
564 * Read more in the [documentation](#!/guide/dev_file_manager_configuration-section-file-manager-window-size)
565 * and see the [SDK sample](http://sdk.ckeditor.com/samples/fileupload.html).
566 *
567 * config.filebrowserWindowHeight = 580;
568 *
569 * config.filebrowserWindowHeight = '50%';
570 *
571 * @cfg {Number/String} [filebrowserWindowHeight='70%']
572 * @member CKEDITOR.config
573 */