diff options
Diffstat (limited to 'sources/core/creators/themedui.js')
-rw-r--r-- | sources/core/creators/themedui.js | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/sources/core/creators/themedui.js b/sources/core/creators/themedui.js new file mode 100644 index 00000000..b8bfcf3d --- /dev/null +++ b/sources/core/creators/themedui.js | |||
@@ -0,0 +1,541 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | /** @class CKEDITOR */ | ||
7 | |||
8 | /** | ||
9 | * The class name used to identify `<textarea>` elements to be replaced | ||
10 | * by CKEditor instances. Set it to empty/`null` to disable this feature. | ||
11 | * | ||
12 | * CKEDITOR.replaceClass = 'rich_editor'; | ||
13 | * | ||
14 | * @cfg {String} [replaceClass='ckeditor'] | ||
15 | */ | ||
16 | CKEDITOR.replaceClass = 'ckeditor'; | ||
17 | |||
18 | ( function() { | ||
19 | /** | ||
20 | * Replaces a `<textarea>` or a DOM element (`<div>`) with a CKEditor | ||
21 | * instance. For textareas, the initial value in the editor will be the | ||
22 | * textarea value. For DOM elements, their `innerHTML` will be used | ||
23 | * instead. We recommend using `<textarea>` and `<div>` elements only. | ||
24 | * | ||
25 | * <textarea id="myfield" name="myfield"></textarea> | ||
26 | * ... | ||
27 | * CKEDITOR.replace( 'myfield' ); | ||
28 | * | ||
29 | * var textarea = document.body.appendChild( document.createElement( 'textarea' ) ); | ||
30 | * CKEDITOR.replace( textarea ); | ||
31 | * | ||
32 | * @param {Object/String} element The DOM element (textarea), its ID, or name. | ||
33 | * @param {Object} [config] The specific configuration to apply to this | ||
34 | * editor instance. Configuration set here will override the global CKEditor settings | ||
35 | * (see {@link CKEDITOR.config}). | ||
36 | * @returns {CKEDITOR.editor} The editor instance created. | ||
37 | */ | ||
38 | CKEDITOR.replace = function( element, config ) { | ||
39 | return createInstance( element, config, null, CKEDITOR.ELEMENT_MODE_REPLACE ); | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * Creates a new editor instance at the end of a specific DOM element. | ||
44 | * | ||
45 | * <!DOCTYPE html> | ||
46 | * <html> | ||
47 | * <head> | ||
48 | * <meta charset="utf-8"> | ||
49 | * <title>CKEditor</title> | ||
50 | * <!-- Make sure the path to CKEditor is correct. --> | ||
51 | * <script src="/ckeditor/ckeditor.js"></script> | ||
52 | * </head> | ||
53 | * <body> | ||
54 | * <div id="editorSpace"></div> | ||
55 | * <script> | ||
56 | * CKEDITOR.appendTo( 'editorSpace' ); | ||
57 | * </script> | ||
58 | * </body> | ||
59 | * </html> | ||
60 | * | ||
61 | * @param {Object/String} element The DOM element, its ID, or name. | ||
62 | * @param {Object} [config] The specific configuration to apply to this | ||
63 | * editor instance. Configuration set here will override the global CKEditor settings | ||
64 | * (see {@link CKEDITOR.config}). | ||
65 | * @param {String} [data] Since 3.3. Initial value for the instance. | ||
66 | * @returns {CKEDITOR.editor} The editor instance created. | ||
67 | */ | ||
68 | CKEDITOR.appendTo = function( element, config, data ) { | ||
69 | return createInstance( element, config, data, CKEDITOR.ELEMENT_MODE_APPENDTO ); | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * Replaces all `<textarea>` elements available in the document with | ||
74 | * editor instances. | ||
75 | * | ||
76 | * // Replace all <textarea> elements in the page. | ||
77 | * CKEDITOR.replaceAll(); | ||
78 | * | ||
79 | * // Replace all <textarea class="myClassName"> elements in the page. | ||
80 | * CKEDITOR.replaceAll( 'myClassName' ); | ||
81 | * | ||
82 | * // Selectively replace <textarea> elements, based on custom assertions. | ||
83 | * CKEDITOR.replaceAll( function( textarea, config ) { | ||
84 | * // An assertion function that needs to be evaluated for the <textarea> | ||
85 | * // to be replaced. It must explicitely return "false" to ignore a | ||
86 | * // specific <textarea>. | ||
87 | * // You can also customize the editor instance by having the function | ||
88 | * // modify the "config" parameter. | ||
89 | * } ); | ||
90 | * | ||
91 | * // Full page example where three <textarea> elements are replaced. | ||
92 | * <!DOCTYPE html> | ||
93 | * <html> | ||
94 | * <head> | ||
95 | * <meta charset="utf-8"> | ||
96 | * <title>CKEditor</title> | ||
97 | * <!-- Make sure the path to CKEditor is correct. --> | ||
98 | * <script src="/ckeditor/ckeditor.js"></script> | ||
99 | * </head> | ||
100 | * <body> | ||
101 | * <textarea name="editor1"></textarea> | ||
102 | * <textarea name="editor2"></textarea> | ||
103 | * <textarea name="editor3"></textarea> | ||
104 | * <script> | ||
105 | * // Replace all three <textarea> elements above with CKEditor instances. | ||
106 | * CKEDITOR.replaceAll(); | ||
107 | * </script> | ||
108 | * </body> | ||
109 | * </html> | ||
110 | * | ||
111 | * @param {String} [className] The `<textarea>` class name. | ||
112 | * @param {Function} [function] An assertion function that must return `true` for a `<textarea>` | ||
113 | * to be replaced with the editor. If the function returns `false`, the `<textarea>` element | ||
114 | * will not be replaced. | ||
115 | */ | ||
116 | CKEDITOR.replaceAll = function() { | ||
117 | var textareas = document.getElementsByTagName( 'textarea' ); | ||
118 | |||
119 | for ( var i = 0; i < textareas.length; i++ ) { | ||
120 | var config = null, | ||
121 | textarea = textareas[ i ]; | ||
122 | |||
123 | // The "name" and/or "id" attribute must exist. | ||
124 | if ( !textarea.name && !textarea.id ) | ||
125 | continue; | ||
126 | |||
127 | if ( typeof arguments[ 0 ] == 'string' ) { | ||
128 | // The textarea class name could be passed as the function | ||
129 | // parameter. | ||
130 | |||
131 | var classRegex = new RegExp( '(?:^|\\s)' + arguments[ 0 ] + '(?:$|\\s)' ); | ||
132 | |||
133 | if ( !classRegex.test( textarea.className ) ) | ||
134 | continue; | ||
135 | } else if ( typeof arguments[ 0 ] == 'function' ) { | ||
136 | // An assertion function could be passed as the function parameter. | ||
137 | // It must explicitly return "false" to ignore a specific <textarea>. | ||
138 | config = {}; | ||
139 | if ( arguments[ 0 ]( textarea, config ) === false ) | ||
140 | continue; | ||
141 | } | ||
142 | |||
143 | this.replace( textarea, config ); | ||
144 | } | ||
145 | }; | ||
146 | |||
147 | /** @class CKEDITOR.editor */ | ||
148 | |||
149 | /** | ||
150 | * Registers an editing mode. This function is to be used mainly by plugins. | ||
151 | * | ||
152 | * @param {String} mode The mode name. | ||
153 | * @param {Function} exec The function that performs the actual mode change. | ||
154 | */ | ||
155 | CKEDITOR.editor.prototype.addMode = function( mode, exec ) { | ||
156 | ( this._.modes || ( this._.modes = {} ) )[ mode ] = exec; | ||
157 | }; | ||
158 | |||
159 | /** | ||
160 | * Changes the editing mode of this editor instance. | ||
161 | * | ||
162 | * **Note:** The mode switch could be asynchronous depending on the mode provider. | ||
163 | * Use the `callback` to hook subsequent code. | ||
164 | * | ||
165 | * // Switch to "source" view. | ||
166 | * CKEDITOR.instances.editor1.setMode( 'source' ); | ||
167 | * // Switch to "wysiwyg" view and be notified on completion. | ||
168 | * CKEDITOR.instances.editor1.setMode( 'wysiwyg', function() { alert( 'wysiwyg mode loaded!' ); } ); | ||
169 | * | ||
170 | * @param {String} [newMode] If not specified, the {@link CKEDITOR.config#startupMode} will be used. | ||
171 | * @param {Function} [callback] Optional callback function which is invoked once the mode switch has succeeded. | ||
172 | */ | ||
173 | CKEDITOR.editor.prototype.setMode = function( newMode, callback ) { | ||
174 | var editor = this; | ||
175 | |||
176 | var modes = this._.modes; | ||
177 | |||
178 | // Mode loading quickly fails. | ||
179 | if ( newMode == editor.mode || !modes || !modes[ newMode ] ) | ||
180 | return; | ||
181 | |||
182 | editor.fire( 'beforeSetMode', newMode ); | ||
183 | |||
184 | if ( editor.mode ) { | ||
185 | var isDirty = editor.checkDirty(), | ||
186 | previousModeData = editor._.previousModeData, | ||
187 | currentData, | ||
188 | unlockSnapshot = 0; | ||
189 | |||
190 | editor.fire( 'beforeModeUnload' ); | ||
191 | |||
192 | // Detach the current editable. While detaching editable will set | ||
193 | // cached editor's data (with internal setData call). We use this | ||
194 | // data below to avoid two getData() calls in a row. | ||
195 | editor.editable( 0 ); | ||
196 | |||
197 | editor._.previousMode = editor.mode; | ||
198 | // Get cached data, which was set while detaching editable. | ||
199 | editor._.previousModeData = currentData = editor.getData( 1 ); | ||
200 | |||
201 | // If data has not been modified in the mode which we are currently leaving, | ||
202 | // avoid making snapshot right after initializing new mode. | ||
203 | // http://dev.ckeditor.com/ticket/5217#comment:20 | ||
204 | // Tested by: | ||
205 | // 'test switch mode with unrecoreded, inner HTML specific content (boguses)' | ||
206 | // 'test switch mode with unrecoreded, inner HTML specific content (boguses) plus changes in source mode' | ||
207 | if ( editor.mode == 'source' && previousModeData == currentData ) { | ||
208 | // We need to make sure that unlockSnapshot will update the last snapshot | ||
209 | // (will not create new one) if lockSnapshot is not called on outdated snapshots stack. | ||
210 | // Additionally, forceUpdate prevents from making content image now, which is useless | ||
211 | // (because it equals editor data not inner HTML). | ||
212 | editor.fire( 'lockSnapshot', { forceUpdate: true } ); | ||
213 | unlockSnapshot = 1; | ||
214 | } | ||
215 | |||
216 | // Clear up the mode space. | ||
217 | editor.ui.space( 'contents' ).setHtml( '' ); | ||
218 | |||
219 | editor.mode = ''; | ||
220 | } else { | ||
221 | editor._.previousModeData = editor.getData( 1 ); | ||
222 | } | ||
223 | |||
224 | // Fire the mode handler. | ||
225 | this._.modes[ newMode ]( function() { | ||
226 | // Set the current mode. | ||
227 | editor.mode = newMode; | ||
228 | |||
229 | if ( isDirty !== undefined ) | ||
230 | !isDirty && editor.resetDirty(); | ||
231 | |||
232 | if ( unlockSnapshot ) | ||
233 | editor.fire( 'unlockSnapshot' ); | ||
234 | // Since snapshot made on dataReady (which normally catches changes done by setData) | ||
235 | // won't work because editor.mode was not set yet (it's set in this function), we need | ||
236 | // to make special snapshot for changes done in source mode here. | ||
237 | else if ( newMode == 'wysiwyg' ) | ||
238 | editor.fire( 'saveSnapshot' ); | ||
239 | |||
240 | // Delay to avoid race conditions (setMode inside setMode). | ||
241 | setTimeout( function() { | ||
242 | editor.fire( 'mode' ); | ||
243 | callback && callback.call( editor ); | ||
244 | }, 0 ); | ||
245 | } ); | ||
246 | }; | ||
247 | |||
248 | /** | ||
249 | * Resizes the editor interface. | ||
250 | * | ||
251 | * editor.resize( 900, 300 ); | ||
252 | * | ||
253 | * editor.resize( '100%', 450, true ); | ||
254 | * | ||
255 | * @param {Number/String} width The new width. It can be an integer denoting a value | ||
256 | * in pixels or a CSS size value with unit. | ||
257 | * @param {Number/String} height The new height. It can be an integer denoting a value | ||
258 | * in pixels or a CSS size value with unit. | ||
259 | * @param {Boolean} [isContentHeight] Indicates that the provided height is to | ||
260 | * be applied to the editor content area, and not to the entire editor | ||
261 | * interface. Defaults to `false`. | ||
262 | * @param {Boolean} [resizeInner] Indicates that it is the inner interface | ||
263 | * element that must be resized, not the outer element. The default theme | ||
264 | * defines the editor interface inside a pair of `<span>` elements | ||
265 | * (`<span><span>...</span></span>`). By default the first, | ||
266 | * outer `<span>` element receives the sizes. If this parameter is set to | ||
267 | * `true`, the second, inner `<span>` is resized instead. | ||
268 | */ | ||
269 | CKEDITOR.editor.prototype.resize = function( width, height, isContentHeight, resizeInner ) { | ||
270 | var container = this.container, | ||
271 | contents = this.ui.space( 'contents' ), | ||
272 | contentsFrame = CKEDITOR.env.webkit && this.document && this.document.getWindow().$.frameElement, | ||
273 | outer; | ||
274 | |||
275 | if ( resizeInner ) { | ||
276 | outer = this.container.getFirst( function( node ) { | ||
277 | return node.type == CKEDITOR.NODE_ELEMENT && node.hasClass( 'cke_inner' ); | ||
278 | } ); | ||
279 | } else { | ||
280 | outer = container; | ||
281 | } | ||
282 | |||
283 | // Set as border box width. (#5353) | ||
284 | outer.setSize( 'width', width, true ); | ||
285 | |||
286 | // WebKit needs to refresh the iframe size to avoid rendering issues. (1/2) (#8348) | ||
287 | contentsFrame && ( contentsFrame.style.width = '1%' ); | ||
288 | |||
289 | // Get the height delta between the outer table and the content area. | ||
290 | var contentsOuterDelta = ( outer.$.offsetHeight || 0 ) - ( contents.$.clientHeight || 0 ), | ||
291 | |||
292 | // If we're setting the content area's height, then we don't need the delta. | ||
293 | resultContentsHeight = Math.max( height - ( isContentHeight ? 0 : contentsOuterDelta ), 0 ), | ||
294 | resultOuterHeight = ( isContentHeight ? height + contentsOuterDelta : height ); | ||
295 | |||
296 | contents.setStyle( 'height', resultContentsHeight + 'px' ); | ||
297 | |||
298 | // WebKit needs to refresh the iframe size to avoid rendering issues. (2/2) (#8348) | ||
299 | contentsFrame && ( contentsFrame.style.width = '100%' ); | ||
300 | |||
301 | // Emit a resize event. | ||
302 | this.fire( 'resize', { | ||
303 | outerHeight: resultOuterHeight, | ||
304 | contentsHeight: resultContentsHeight, | ||
305 | // Sometimes width is not provided. | ||
306 | outerWidth: width || outer.getSize( 'width' ) | ||
307 | } ); | ||
308 | }; | ||
309 | |||
310 | /** | ||
311 | * Gets the element that can be used to check the editor size. This method | ||
312 | * is mainly used by the `resize` plugin, which adds a UI handle that can be used | ||
313 | * to resize the editor. | ||
314 | * | ||
315 | * @param {Boolean} forContents Whether to return the "contents" part of the theme instead of the container. | ||
316 | * @returns {CKEDITOR.dom.element} The resizable element. | ||
317 | */ | ||
318 | CKEDITOR.editor.prototype.getResizable = function( forContents ) { | ||
319 | return forContents ? this.ui.space( 'contents' ) : this.container; | ||
320 | }; | ||
321 | |||
322 | function createInstance( element, config, data, mode ) { | ||
323 | if ( !CKEDITOR.env.isCompatible ) | ||
324 | return null; | ||
325 | |||
326 | element = CKEDITOR.dom.element.get( element ); | ||
327 | |||
328 | // Avoid multiple inline editor instances on the same element. | ||
329 | if ( element.getEditor() ) | ||
330 | throw 'The editor instance "' + element.getEditor().name + '" is already attached to the provided element.'; | ||
331 | |||
332 | // Create the editor instance. | ||
333 | var editor = new CKEDITOR.editor( config, element, mode ); | ||
334 | |||
335 | if ( mode == CKEDITOR.ELEMENT_MODE_REPLACE ) { | ||
336 | // Do not replace the textarea right now, just hide it. The effective | ||
337 | // replacement will be done later in the editor creation lifecycle. | ||
338 | element.setStyle( 'visibility', 'hidden' ); | ||
339 | |||
340 | // #8031 Remember if textarea was required and remove the attribute. | ||
341 | editor._.required = element.hasAttribute( 'required' ); | ||
342 | element.removeAttribute( 'required' ); | ||
343 | } | ||
344 | |||
345 | data && editor.setData( data, null, true ); | ||
346 | |||
347 | // Once the editor is loaded, start the UI. | ||
348 | editor.on( 'loaded', function() { | ||
349 | loadTheme( editor ); | ||
350 | |||
351 | if ( mode == CKEDITOR.ELEMENT_MODE_REPLACE && editor.config.autoUpdateElement && element.$.form ) | ||
352 | editor._attachToForm(); | ||
353 | |||
354 | editor.setMode( editor.config.startupMode, function() { | ||
355 | // Clean on startup. | ||
356 | editor.resetDirty(); | ||
357 | |||
358 | // Editor is completely loaded for interaction. | ||
359 | editor.status = 'ready'; | ||
360 | editor.fireOnce( 'instanceReady' ); | ||
361 | CKEDITOR.fire( 'instanceReady', null, editor ); | ||
362 | } ); | ||
363 | } ); | ||
364 | |||
365 | editor.on( 'destroy', destroy ); | ||
366 | return editor; | ||
367 | } | ||
368 | |||
369 | function destroy() { | ||
370 | var editor = this, | ||
371 | container = editor.container, | ||
372 | element = editor.element; | ||
373 | |||
374 | if ( container ) { | ||
375 | container.clearCustomData(); | ||
376 | container.remove(); | ||
377 | } | ||
378 | |||
379 | if ( element ) { | ||
380 | element.clearCustomData(); | ||
381 | if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) { | ||
382 | element.show(); | ||
383 | if ( editor._.required ) | ||
384 | element.setAttribute( 'required', 'required' ); | ||
385 | } | ||
386 | delete editor.element; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | function loadTheme( editor ) { | ||
391 | var name = editor.name, | ||
392 | element = editor.element, | ||
393 | elementMode = editor.elementMode; | ||
394 | |||
395 | // Get the HTML for the predefined spaces. | ||
396 | var topHtml = editor.fire( 'uiSpace', { space: 'top', html: '' } ).html; | ||
397 | var bottomHtml = editor.fire( 'uiSpace', { space: 'bottom', html: '' } ).html; | ||
398 | |||
399 | var themedTpl = new CKEDITOR.template( | ||
400 | '<{outerEl}' + | ||
401 | ' id="cke_{name}"' + | ||
402 | ' class="{id} cke cke_reset cke_chrome cke_editor_{name} cke_{langDir} ' + CKEDITOR.env.cssClass + '" ' + | ||
403 | ' dir="{langDir}"' + | ||
404 | ' lang="{langCode}"' + | ||
405 | ' role="application"' + | ||
406 | ( editor.title ? ' aria-labelledby="cke_{name}_arialbl"' : '' ) + | ||
407 | '>' + | ||
408 | ( editor.title ? '<span id="cke_{name}_arialbl" class="cke_voice_label">{voiceLabel}</span>' : '' ) + | ||
409 | '<{outerEl} class="cke_inner cke_reset" role="presentation">' + | ||
410 | '{topHtml}' + | ||
411 | '<{outerEl} id="{contentId}" class="cke_contents cke_reset" role="presentation"></{outerEl}>' + | ||
412 | '{bottomHtml}' + | ||
413 | '</{outerEl}>' + | ||
414 | '</{outerEl}>' ); | ||
415 | |||
416 | var container = CKEDITOR.dom.element.createFromHtml( themedTpl.output( { | ||
417 | id: editor.id, | ||
418 | name: name, | ||
419 | langDir: editor.lang.dir, | ||
420 | langCode: editor.langCode, | ||
421 | voiceLabel: editor.title, | ||
422 | topHtml: topHtml ? '<span id="' + editor.ui.spaceId( 'top' ) + '" class="cke_top cke_reset_all" role="presentation" style="height:auto">' + topHtml + '</span>' : '', | ||
423 | contentId: editor.ui.spaceId( 'contents' ), | ||
424 | bottomHtml: bottomHtml ? '<span id="' + editor.ui.spaceId( 'bottom' ) + '" class="cke_bottom cke_reset_all" role="presentation">' + bottomHtml + '</span>' : '', | ||
425 | outerEl: CKEDITOR.env.ie ? 'span' : 'div' // #9571 | ||
426 | } ) ); | ||
427 | |||
428 | if ( elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) { | ||
429 | element.hide(); | ||
430 | container.insertAfter( element ); | ||
431 | } else { | ||
432 | element.append( container ); | ||
433 | } | ||
434 | |||
435 | editor.container = container; | ||
436 | editor.ui.contentsElement = editor.ui.space( 'contents' ); | ||
437 | |||
438 | // Make top and bottom spaces unelectable, but not content space, | ||
439 | // otherwise the editable area would be affected. | ||
440 | topHtml && editor.ui.space( 'top' ).unselectable(); | ||
441 | bottomHtml && editor.ui.space( 'bottom' ).unselectable(); | ||
442 | |||
443 | var width = editor.config.width, height = editor.config.height; | ||
444 | if ( width ) | ||
445 | container.setStyle( 'width', CKEDITOR.tools.cssLength( width ) ); | ||
446 | |||
447 | // The editor height is applied to the contents space. | ||
448 | if ( height ) | ||
449 | editor.ui.space( 'contents' ).setStyle( 'height', CKEDITOR.tools.cssLength( height ) ); | ||
450 | |||
451 | // Disable browser context menu for editor's chrome. | ||
452 | container.disableContextMenu(); | ||
453 | |||
454 | // Redirect the focus into editor for webkit. (#5713) | ||
455 | CKEDITOR.env.webkit && container.on( 'focus', function() { | ||
456 | editor.focus(); | ||
457 | } ); | ||
458 | |||
459 | editor.fireOnce( 'uiReady' ); | ||
460 | } | ||
461 | |||
462 | // Replace all textareas with the default class name. | ||
463 | CKEDITOR.domReady( function() { | ||
464 | CKEDITOR.replaceClass && CKEDITOR.replaceAll( CKEDITOR.replaceClass ); | ||
465 | } ); | ||
466 | } )(); | ||
467 | |||
468 | /** | ||
469 | * The current editing mode. An editing mode basically provides | ||
470 | * different ways of editing or viewing the contents. | ||
471 | * | ||
472 | * alert( CKEDITOR.instances.editor1.mode ); // (e.g.) 'wysiwyg' | ||
473 | * | ||
474 | * @readonly | ||
475 | * @property {String} mode | ||
476 | */ | ||
477 | |||
478 | /** | ||
479 | * The mode to load at the editor startup. It depends on the plugins | ||
480 | * loaded. By default, the `wysiwyg` and `source` modes are available. | ||
481 | * | ||
482 | * config.startupMode = 'source'; | ||
483 | * | ||
484 | * @cfg {String} [startupMode='wysiwyg'] | ||
485 | * @member CKEDITOR.config | ||
486 | */ | ||
487 | CKEDITOR.config.startupMode = 'wysiwyg'; | ||
488 | |||
489 | /** | ||
490 | * Fired after the editor instance is resized through | ||
491 | * the {@link CKEDITOR.editor#method-resize CKEDITOR.resize} method. | ||
492 | * | ||
493 | * @event resize | ||
494 | * @param {CKEDITOR.editor} editor This editor instance. | ||
495 | * @param {Object} data Available since CKEditor 4.5. | ||
496 | * @param {Number} data.outerHeight The height of the entire area that the editor covers. | ||
497 | * @param {Number} data.contentsHeight Editable area height in pixels. | ||
498 | * @param {Number} data.outerWidth The width of the entire area that the editor covers. | ||
499 | */ | ||
500 | |||
501 | /** | ||
502 | * Fired before changing the editing mode. See also | ||
503 | * {@link #beforeSetMode} and {@link #event-mode}. | ||
504 | * | ||
505 | * @event beforeModeUnload | ||
506 | * @param {CKEDITOR.editor} editor This editor instance. | ||
507 | */ | ||
508 | |||
509 | /** | ||
510 | * Fired before the editor mode is set. See also | ||
511 | * {@link #event-mode} and {@link #beforeModeUnload}. | ||
512 | * | ||
513 | * @since 3.5.3 | ||
514 | * @event beforeSetMode | ||
515 | * @param {CKEDITOR.editor} editor This editor instance. | ||
516 | * @param {String} data The name of the mode which is about to be set. | ||
517 | */ | ||
518 | |||
519 | /** | ||
520 | * Fired after setting the editing mode. See also {@link #beforeSetMode} and {@link #beforeModeUnload} | ||
521 | * | ||
522 | * @event mode | ||
523 | * @param {CKEDITOR.editor} editor This editor instance. | ||
524 | */ | ||
525 | |||
526 | /** | ||
527 | * Fired when the editor (replacing a `<textarea>` which has a `required` attribute) is empty during form submission. | ||
528 | * | ||
529 | * This event replaces native required fields validation that the browsers cannot | ||
530 | * perform when CKEditor replaces `<textarea>` elements. | ||
531 | * | ||
532 | * You can cancel this event to prevent the page from submitting data. | ||
533 | * | ||
534 | * editor.on( 'required', function( evt ) { | ||
535 | * alert( 'Article content is required.' ); | ||
536 | * evt.cancel(); | ||
537 | * } ); | ||
538 | * | ||
539 | * @event required | ||
540 | * @param {CKEDITOR.editor} editor This editor instance. | ||
541 | */ | ||