2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
11 CKEDITOR
.themes
.add( 'default', (function()
15 function checkSharedSpace( editor
, spaceName
)
20 // Try to retrieve the target element from the sharedSpaces settings.
21 element
= editor
.config
.sharedSpaces
;
22 element
= element
&& element
[ spaceName
];
23 element
= element
&& CKEDITOR
.document
.getById( element
);
25 // If the element is available, we'll then create the container for
29 // Creates an HTML structure that reproduces the editor class hierarchy.
31 '<span class="cke_shared "' +
32 ' dir="'+ editor
.lang
.dir
+ '"' +
34 '<span class="' + editor
.skinClass
+ ' ' + editor
.id
+ ' cke_editor_' + editor
.name
+ '">' +
35 '<span class="' + CKEDITOR
.env
.cssClass
+ '">' +
36 '<span class="cke_wrapper cke_' + editor
.lang
.dir
+ '">' +
37 '<span class="cke_editor">' +
38 '<div class="cke_' + spaceName
+ '">' +
39 '</div></span></span></span></span></span>';
41 var mainContainer
= element
.append( CKEDITOR
.dom
.element
.createFromHtml( html
, element
.getDocument() ) );
43 // Only the first container starts visible. Others get hidden.
44 if ( element
.getCustomData( 'cke_hasshared' ) )
47 element
.setCustomData( 'cke_hasshared', 1 );
49 // Get the deeper inner <div>.
50 container
= mainContainer
.getChild( [0,0,0,0] );
52 // Save a reference to the shared space container.
53 !editor
.sharedSpaces
&& ( editor
.sharedSpaces
= {} );
54 editor
.sharedSpaces
[ spaceName
] = container
;
56 // When the editor gets focus, we show the space container, hiding others.
57 editor
.on( 'focus', function()
59 for ( var i
= 0, sibling
, children
= element
.getChildren() ; ( sibling
= children
.getItem( i
) ) ; i
++ )
61 if ( sibling
.type
== CKEDITOR
.NODE_ELEMENT
62 && !sibling
.equals( mainContainer
)
63 && sibling
.hasClass( 'cke_shared' ) )
72 editor
.on( 'destroy', function()
74 mainContainer
.remove();
81 return /** @lends CKEDITOR.theme */ {
82 build : function( editor
, themePath
)
84 var name
= editor
.name
,
85 element
= editor
.element
,
86 elementMode
= editor
.elementMode
;
88 if ( !element
|| elementMode
== CKEDITOR
.ELEMENT_MODE_NONE
)
91 if ( elementMode
== CKEDITOR
.ELEMENT_MODE_REPLACE
)
94 // Get the HTML for the predefined spaces.
95 var topHtml
= editor
.fire( 'themeSpace', { space
: 'top', html
: '' } ).html
;
96 var contentsHtml
= editor
.fire( 'themeSpace', { space
: 'contents', html
: '' } ).html
;
97 var bottomHtml
= editor
.fireOnce( 'themeSpace', { space
: 'bottom', html
: '' } ).html
;
99 var height
= contentsHtml
&& editor
.config
.height
;
101 var tabIndex
= editor
.config
.tabIndex
|| editor
.element
.getAttribute( 'tabindex' ) || 0;
103 // The editor height is considered only if the contents space got filled.
106 else if ( !isNaN( height
) )
110 var width
= editor
.config
.width
;
114 if ( !isNaN( width
) )
117 style
+= "width: " + width
+ ";";
120 var sharedTop
= topHtml
&& checkSharedSpace( editor
, 'top' ),
121 sharedBottoms
= checkSharedSpace( editor
, 'bottom' );
123 sharedTop
&& ( sharedTop
.setHtml( topHtml
) , topHtml
= '' );
124 sharedBottoms
&& ( sharedBottoms
.setHtml( bottomHtml
), bottomHtml
= '' );
126 var hideSkin
= '<style>.' + editor
.skinClass
+ '{visibility:hidden;}</style>';
127 if ( hiddenSkins
[ editor
.skinClass
] )
130 hiddenSkins
[ editor
.skinClass
] = 1;
132 var container
= CKEDITOR
.dom
.element
.createFromHtml( [
134 ' id="cke_', name
, '"' +
135 ' class="', editor
.skinClass
, ' ', editor
.id
, ' cke_editor_', name
, '"' +
136 ' dir="', editor
.lang
.dir
, '"' +
137 ' title="', ( CKEDITOR
.env
.gecko
? ' ' : '' ), '"' +
138 ' lang="', editor
.langCode
, '"' +
139 ( CKEDITOR
.env
.webkit
? ' tabindex="' + tabIndex
+ '"' : '' ) +
140 ' role="application"' +
141 ' aria-labelledby="cke_', name
, '_arialbl"' +
142 ( style
? ' style="' + style
+ '"' : '' ) +
144 '<span id="cke_', name
, '_arialbl" class="cke_voice_label">' + editor
.lang
.editor
+ '</span>' +
145 '<span class="' , CKEDITOR
.env
.cssClass
, '" role="presentation">' +
146 '<span class="cke_wrapper cke_', editor
.lang
.dir
, '" role="presentation">' +
147 '<table class="cke_editor" border="0" cellspacing="0" cellpadding="0" role="presentation"><tbody>' +
148 '<tr', topHtml
? '' : ' style="display:none"', ' role="presentation"><td id="cke_top_' , name
, '" class="cke_top" role="presentation">' , topHtml
, '</td></tr>' +
149 '<tr', contentsHtml
? '' : ' style="display:none"', ' role="presentation"><td id="cke_contents_', name
, '" class="cke_contents" style="height:', height
, '" role="presentation">', contentsHtml
, '</td></tr>' +
150 '<tr', bottomHtml
? '' : ' style="display:none"', ' role="presentation"><td id="cke_bottom_' , name
, '" class="cke_bottom" role="presentation">' , bottomHtml
, '</td></tr>' +
152 //Hide the container when loading skins, later restored by skin css.
156 '</span>' ].join( '' ) );
158 container
.getChild( [1, 0, 0, 0, 0] ).unselectable();
159 container
.getChild( [1, 0, 0, 0, 2] ).unselectable();
161 if ( elementMode
== CKEDITOR
.ELEMENT_MODE_REPLACE
)
162 container
.insertAfter( element
);
164 element
.append( container
);
167 * The DOM element that holds the main editor interface.
168 * @name CKEDITOR.editor.prototype.container
169 * @type CKEDITOR.dom.element
171 * var editor = CKEDITOR.instances.editor1;
172 * alert( <b>editor.container</b>.getName() ); "span"
174 editor
.container
= container
;
176 // Disable browser context menu for editor's chrome.
177 container
.disableContextMenu();
179 // Use a class to indicate that the current selection is in different direction than the UI.
180 editor
.on( 'contentDirChanged', function( evt
)
182 var func
= ( editor
.lang
.dir
!= evt
.data
? 'add' : 'remove' ) + 'Class';
184 container
.getChild( 1 )[ func
]( 'cke_mixed_dir_content' );
186 // Put the mixed direction class on the respective element also for shared spaces.
187 var toolbarSpace
= this.sharedSpaces
&& this.sharedSpaces
[ this.config
.toolbarLocation
];
188 toolbarSpace
&& toolbarSpace
.getParent().getParent()[ func
]( 'cke_mixed_dir_content' );
191 editor
.fireOnce( 'themeLoaded' );
192 editor
.fireOnce( 'uiReady' );
195 buildDialog : function( editor
)
197 var baseIdNumber
= CKEDITOR
.tools
.getNextNumber();
199 var element
= CKEDITOR
.dom
.element
.createFromHtml( [
200 '<div class="', editor
.id
, '_dialog cke_editor_', editor
.name
.replace('.', '\\.'), '_dialog cke_skin_', editor
.skinName
,
201 '" dir="', editor
.lang
.dir
, '"' +
202 ' lang="', editor
.langCode
, '"' +
204 ' aria-labelledby="%title#"' +
206 '<table class="cke_dialog', ' ' + CKEDITOR
.env
.cssClass
,
207 ' cke_', editor
.lang
.dir
, '" style="position:absolute" role="presentation">' +
208 '<tr><td role="presentation">' +
209 '<div class="%body" role="presentation">' +
210 '<div id="%title#" class="%title" role="presentation"></div>' +
211 '<a id="%close_button#" class="%close_button" href="javascript:void(0)" title="' + editor
.lang
.common
.close
+'" role="button"><span class="cke_label">X</span></a>' +
212 '<div id="%tabs#" class="%tabs" role="tablist"></div>' +
213 '<table class="%contents" role="presentation">' +
215 '<td id="%contents#" class="%contents" role="presentation"></td>' +
218 '<td id="%footer#" class="%footer" role="presentation"></td>' +
222 '<div id="%tl#" class="%tl"></div>' +
223 '<div id="%tc#" class="%tc"></div>' +
224 '<div id="%tr#" class="%tr"></div>' +
225 '<div id="%ml#" class="%ml"></div>' +
226 '<div id="%mr#" class="%mr"></div>' +
227 '<div id="%bl#" class="%bl"></div>' +
228 '<div id="%bc#" class="%bc"></div>' +
229 '<div id="%br#" class="%br"></div>' +
233 //Hide the container when loading skins, later restored by skin css.
234 ( CKEDITOR
.env
.ie
? '' : '<style>.cke_dialog{visibility:hidden;}</style>' ),
238 .replace( /#/g
, '_' + baseIdNumber
)
239 .replace( /%/g
, 'cke_dialog_' ) );
241 var body
= element
.getChild( [ 0, 0, 0, 0, 0 ] ),
242 title
= body
.getChild( 0 ),
243 close
= body
.getChild( 1 );
245 // Make the Title and Close Button unselectable.
246 title
.unselectable();
247 close
.unselectable();
254 dialog
: element
.getChild( 0 ),
257 tabs
: body
.getChild( 2 ),
258 contents
: body
.getChild( [ 3, 0, 0, 0 ] ),
259 footer
: body
.getChild( [ 3, 0, 1, 0 ] )
264 destroy : function( editor
)
266 var container
= editor
.container
,
267 element
= editor
.element
;
271 container
.clearCustomData();
277 element
.clearCustomData();
278 editor
.elementMode
== CKEDITOR
.ELEMENT_MODE_REPLACE
&& element
.show();
279 delete editor
.element
;
286 * Returns the DOM element that represents a theme space. The default theme defines
287 * three spaces, namely "top", "contents" and "bottom", representing the main
288 * blocks that compose the editor interface.
289 * @param {String} spaceName The space name.
290 * @returns {CKEDITOR.dom.element} The element that represents the space.
292 * // Hide the bottom space in the UI.
293 * var bottom = editor.getThemeSpace( 'bottom' );
294 * bottom.setStyle( 'display', 'none' );
296 CKEDITOR
.editor
.prototype.getThemeSpace = function( spaceName
)
298 var spacePrefix
= 'cke_' + spaceName
;
299 var space
= this._
[ spacePrefix
] ||
300 ( this._
[ spacePrefix
] = CKEDITOR
.document
.getById( spacePrefix
+ '_' + this.name
) );
305 * Resizes the editor interface.
306 * @param {Number|String} width The new width. It can be an pixels integer or a
308 * @param {Number|String} height The new height. It can be an pixels integer or
310 * @param {Boolean} [isContentHeight] Indicates that the provided height is to
311 * be applied to the editor contents space, not to the entire editor
312 * interface. Defaults to false.
313 * @param {Boolean} [resizeInner] Indicates that the first inner interface
314 * element must receive the size, not the outer element. The default theme
315 * defines the interface inside a pair of span elements
316 * (<span><span>...</span></span>). By default the
317 * first span element receives the sizes. If this parameter is set to
318 * true, the second span is sized instead.
320 * editor.resize( 900, 300 );
322 * editor.resize( '100%', 450, true );
324 CKEDITOR
.editor
.prototype.resize = function( width
, height
, isContentHeight
, resizeInner
)
326 var container
= this.container
,
327 contents
= CKEDITOR
.document
.getById( 'cke_contents_' + this.name
),
328 outer
= resizeInner
? container
.getChild( 1 ) : container
;
330 // Resize the width first.
331 // WEBKIT BUG: Webkit requires that we put the editor off from display when we
332 // resize it. If we don't, the browser crashes!
333 CKEDITOR
.env
.webkit
&& outer
.setStyle( 'display', 'none' );
334 // Set as border box width. (#5353)
335 outer
.setSize( 'width', width
, true );
336 if ( CKEDITOR
.env
.webkit
)
339 outer
.setStyle( 'display', '' );
342 // Get the height delta between the outer table and the content area.
343 // If we're setting the content area's height, then we don't need the delta.
344 var delta
= isContentHeight
? 0 : ( outer
.$.offsetHeight
|| 0 ) - ( contents
.$.clientHeight
|| 0 );
345 contents
.setStyle( 'height', Math
.max( height
- delta
, 0 ) + 'px' );
347 // Emit a resize event.
348 this.fire( 'resize' );
352 * Gets the element that can be freely used to check the editor size. This method
353 * is mainly used by the resize plugin, which adds a UI handle that can be used
354 * to resize the editor.
355 * @param {Boolean} forContents Whether to return the "contents" part of the theme instead of the container.
356 * @returns {CKEDITOR.dom.element} The resizable element.
359 CKEDITOR
.editor
.prototype.getResizable = function( forContents
)
361 return forContents
? CKEDITOR
.document
.getById( 'cke_contents_' + this.name
) : this.container
;
365 * Makes it possible to place some of the editor UI blocks, like the toolbar
366 * and the elements path, into any element in the page.
367 * The elements used to hold the UI blocks can be shared among several editor
368 * instances. In that case, only the blocks of the active editor instance will
370 * @name CKEDITOR.config.sharedSpaces
374 * // Place the toolbar inside the element with ID "someElementId" and the
375 * // elements path into the element with ID "anotherId".
376 * config.sharedSpaces =
378 * top : 'someElementId',
379 * bottom : 'anotherId'
382 * // Place the toolbar inside the element with ID "someElementId". The
383 * // elements path will remain attached to the editor UI.
384 * config.sharedSpaces =
386 * top : 'someElementId'
391 * Fired after the editor instance is resized through
392 * the {@link CKEDITOR.editor.prototype.resize} method.
393 * @name CKEDITOR.editor#resize