2593905d5cbae859e0d8aab3b5988745b49f3f55.svn-base
14.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/*
Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
* @name CKEDITOR.theme
* @class
*/
CKEDITOR.themes.add( 'default', (function()
{
var hiddenSkins = {};
function checkSharedSpace( editor, spaceName )
{
var container,
element;
// Try to retrieve the target element from the sharedSpaces settings.
element = editor.config.sharedSpaces;
element = element && element[ spaceName ];
element = element && CKEDITOR.document.getById( element );
// If the element is available, we'll then create the container for
// the space.
if ( element )
{
// Creates an HTML structure that reproduces the editor class hierarchy.
var html =
'<span class="cke_shared "' +
' dir="'+ editor.lang.dir + '"' +
'>' +
'<span class="' + editor.skinClass + ' ' + editor.id + ' cke_editor_' + editor.name + '">' +
'<span class="' + CKEDITOR.env.cssClass + '">' +
'<span class="cke_wrapper cke_' + editor.lang.dir + '">' +
'<span class="cke_editor">' +
'<div class="cke_' + spaceName + '">' +
'</div></span></span></span></span></span>';
var mainContainer = element.append( CKEDITOR.dom.element.createFromHtml( html, element.getDocument() ) );
// Only the first container starts visible. Others get hidden.
if ( element.getCustomData( 'cke_hasshared' ) )
mainContainer.hide();
else
element.setCustomData( 'cke_hasshared', 1 );
// Get the deeper inner <div>.
container = mainContainer.getChild( [0,0,0,0] );
// Save a reference to the shared space container.
!editor.sharedSpaces && ( editor.sharedSpaces = {} );
editor.sharedSpaces[ spaceName ] = container;
// When the editor gets focus, we show the space container, hiding others.
editor.on( 'focus', function()
{
for ( var i = 0, sibling, children = element.getChildren() ; ( sibling = children.getItem( i ) ) ; i++ )
{
if ( sibling.type == CKEDITOR.NODE_ELEMENT
&& !sibling.equals( mainContainer )
&& sibling.hasClass( 'cke_shared' ) )
{
sibling.hide();
}
}
mainContainer.show();
});
editor.on( 'destroy', function()
{
mainContainer.remove();
});
}
return container;
}
return /** @lends CKEDITOR.theme */ {
build : function( editor, themePath )
{
var name = editor.name,
element = editor.element,
elementMode = editor.elementMode;
if ( !element || elementMode == CKEDITOR.ELEMENT_MODE_NONE )
return;
if ( elementMode == CKEDITOR.ELEMENT_MODE_REPLACE )
element.hide();
// Get the HTML for the predefined spaces.
var topHtml = editor.fire( 'themeSpace', { space : 'top', html : '' } ).html;
var contentsHtml = editor.fire( 'themeSpace', { space : 'contents', html : '' } ).html;
var bottomHtml = editor.fireOnce( 'themeSpace', { space : 'bottom', html : '' } ).html;
var height = contentsHtml && editor.config.height;
var tabIndex = editor.config.tabIndex || editor.element.getAttribute( 'tabindex' ) || 0;
// The editor height is considered only if the contents space got filled.
if ( !contentsHtml )
height = 'auto';
else if ( !isNaN( height ) )
height += 'px';
var style = '';
var width = editor.config.width;
if ( width )
{
if ( !isNaN( width ) )
width += 'px';
style += "width: " + width + ";";
}
var sharedTop = topHtml && checkSharedSpace( editor, 'top' ),
sharedBottoms = checkSharedSpace( editor, 'bottom' );
sharedTop && ( sharedTop.setHtml( topHtml ) , topHtml = '' );
sharedBottoms && ( sharedBottoms.setHtml( bottomHtml ), bottomHtml = '' );
var hideSkin = '<style>.' + editor.skinClass + '{visibility:hidden;}</style>';
if ( hiddenSkins[ editor.skinClass ] )
hideSkin = '';
else
hiddenSkins[ editor.skinClass ] = 1;
var container = CKEDITOR.dom.element.createFromHtml( [
'<span' +
' id="cke_', name, '"' +
' class="', editor.skinClass, ' ', editor.id, ' cke_editor_', name, '"' +
' dir="', editor.lang.dir, '"' +
' title="', ( CKEDITOR.env.gecko ? ' ' : '' ), '"' +
' lang="', editor.langCode, '"' +
( CKEDITOR.env.webkit? ' tabindex="' + tabIndex + '"' : '' ) +
' role="application"' +
' aria-labelledby="cke_', name, '_arialbl"' +
( style ? ' style="' + style + '"' : '' ) +
'>' +
'<span id="cke_', name, '_arialbl" class="cke_voice_label">' + editor.lang.editor + '</span>' +
'<span class="' , CKEDITOR.env.cssClass, '" role="presentation">' +
'<span class="cke_wrapper cke_', editor.lang.dir, '" role="presentation">' +
'<table class="cke_editor" border="0" cellspacing="0" cellpadding="0" role="presentation"><tbody>' +
'<tr', topHtml ? '' : ' style="display:none"', ' role="presentation"><td id="cke_top_' , name, '" class="cke_top" role="presentation">' , topHtml , '</td></tr>' +
'<tr', contentsHtml ? '' : ' style="display:none"', ' role="presentation"><td id="cke_contents_', name, '" class="cke_contents" style="height:', height, '" role="presentation">', contentsHtml, '</td></tr>' +
'<tr', bottomHtml ? '' : ' style="display:none"', ' role="presentation"><td id="cke_bottom_' , name, '" class="cke_bottom" role="presentation">' , bottomHtml , '</td></tr>' +
'</tbody></table>' +
//Hide the container when loading skins, later restored by skin css.
hideSkin +
'</span>' +
'</span>' +
'</span>' ].join( '' ) );
container.getChild( [1, 0, 0, 0, 0] ).unselectable();
container.getChild( [1, 0, 0, 0, 2] ).unselectable();
if ( elementMode == CKEDITOR.ELEMENT_MODE_REPLACE )
container.insertAfter( element );
else
element.append( container );
/**
* The DOM element that holds the main editor interface.
* @name CKEDITOR.editor.prototype.container
* @type CKEDITOR.dom.element
* @example
* var editor = CKEDITOR.instances.editor1;
* alert( <b>editor.container</b>.getName() ); "span"
*/
editor.container = container;
// Disable browser context menu for editor's chrome.
container.disableContextMenu();
// Use a class to indicate that the current selection is in different direction than the UI.
editor.on( 'contentDirChanged', function( evt )
{
var func = ( editor.lang.dir != evt.data ? 'add' : 'remove' ) + 'Class';
container.getChild( 1 )[ func ]( 'cke_mixed_dir_content' );
// Put the mixed direction class on the respective element also for shared spaces.
var toolbarSpace = this.sharedSpaces && this.sharedSpaces[ this.config.toolbarLocation ];
toolbarSpace && toolbarSpace.getParent().getParent()[ func ]( 'cke_mixed_dir_content' );
});
editor.fireOnce( 'themeLoaded' );
editor.fireOnce( 'uiReady' );
},
buildDialog : function( editor )
{
var baseIdNumber = CKEDITOR.tools.getNextNumber();
var element = CKEDITOR.dom.element.createFromHtml( [
'<div class="', editor.id, '_dialog cke_editor_', editor.name.replace('.', '\\.'), '_dialog cke_skin_', editor.skinName,
'" dir="', editor.lang.dir, '"' +
' lang="', editor.langCode, '"' +
' role="dialog"' +
' aria-labelledby="%title#"' +
'>' +
'<table class="cke_dialog', ' ' + CKEDITOR.env.cssClass,
' cke_', editor.lang.dir, '" style="position:absolute" role="presentation">' +
'<tr><td role="presentation">' +
'<div class="%body" role="presentation">' +
'<div id="%title#" class="%title" role="presentation"></div>' +
'<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>' +
'<div id="%tabs#" class="%tabs" role="tablist"></div>' +
'<table class="%contents" role="presentation">' +
'<tr>' +
'<td id="%contents#" class="%contents" role="presentation"></td>' +
'</tr>' +
'<tr>' +
'<td id="%footer#" class="%footer" role="presentation"></td>' +
'</tr>' +
'</table>' +
'</div>' +
'<div id="%tl#" class="%tl"></div>' +
'<div id="%tc#" class="%tc"></div>' +
'<div id="%tr#" class="%tr"></div>' +
'<div id="%ml#" class="%ml"></div>' +
'<div id="%mr#" class="%mr"></div>' +
'<div id="%bl#" class="%bl"></div>' +
'<div id="%bc#" class="%bc"></div>' +
'<div id="%br#" class="%br"></div>' +
'</td></tr>' +
'</table>',
//Hide the container when loading skins, later restored by skin css.
( CKEDITOR.env.ie ? '' : '<style>.cke_dialog{visibility:hidden;}</style>' ),
'</div>'
].join( '' )
.replace( /#/g, '_' + baseIdNumber )
.replace( /%/g, 'cke_dialog_' ) );
var body = element.getChild( [ 0, 0, 0, 0, 0 ] ),
title = body.getChild( 0 ),
close = body.getChild( 1 );
// IFrame shim for dialog that masks activeX in IE. (#7619)
if ( CKEDITOR.env.ie && !CKEDITOR.env.ie6Compat )
{
var isCustomDomain = CKEDITOR.env.isCustomDomain(),
src = 'javascript:void(function(){' + encodeURIComponent( 'document.open();' + ( isCustomDomain ? ( 'document.domain="' + document.domain + '";' ) : '' ) + 'document.close();' ) + '}())',
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +
' frameBorder="0"' +
' class="cke_iframe_shim"' +
' src="' + src + '"' +
' tabIndex="-1"' +
'></iframe>' );
iframe.appendTo( body.getParent() );
}
// Make the Title and Close Button unselectable.
title.unselectable();
close.unselectable();
return {
element : element,
parts :
{
dialog : element.getChild( 0 ),
title : title,
close : close,
tabs : body.getChild( 2 ),
contents : body.getChild( [ 3, 0, 0, 0 ] ),
footer : body.getChild( [ 3, 0, 1, 0 ] )
}
};
},
destroy : function( editor )
{
var container = editor.container,
element = editor.element;
if ( container )
{
container.clearCustomData();
container.remove();
}
if ( element )
{
element.clearCustomData();
editor.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE && element.show();
delete editor.element;
}
}
};
})() );
/**
* Returns the DOM element that represents a theme space. The default theme defines
* three spaces, namely "top", "contents" and "bottom", representing the main
* blocks that compose the editor interface.
* @param {String} spaceName The space name.
* @returns {CKEDITOR.dom.element} The element that represents the space.
* @example
* // Hide the bottom space in the UI.
* var bottom = editor.getThemeSpace( 'bottom' );
* bottom.setStyle( 'display', 'none' );
*/
CKEDITOR.editor.prototype.getThemeSpace = function( spaceName )
{
var spacePrefix = 'cke_' + spaceName;
var space = this._[ spacePrefix ] ||
( this._[ spacePrefix ] = CKEDITOR.document.getById( spacePrefix + '_' + this.name ) );
return space;
};
/**
* Resizes the editor interface.
* @param {Number|String} width The new width. It can be an pixels integer or a
* CSS size value.
* @param {Number|String} height The new height. It can be an pixels integer or
* a CSS size value.
* @param {Boolean} [isContentHeight] Indicates that the provided height is to
* be applied to the editor contents space, not to the entire editor
* interface. Defaults to false.
* @param {Boolean} [resizeInner] Indicates that the first inner interface
* element must receive the size, not the outer element. The default theme
* defines the interface inside a pair of span elements
* (<span><span>...</span></span>). By default the
* first span element receives the sizes. If this parameter is set to
* true, the second span is sized instead.
* @example
* editor.resize( 900, 300 );
* @example
* editor.resize( '100%', 450, true );
*/
CKEDITOR.editor.prototype.resize = function( width, height, isContentHeight, resizeInner )
{
var container = this.container,
contents = CKEDITOR.document.getById( 'cke_contents_' + this.name ),
contentsFrame = CKEDITOR.env.webkit && this.document && this.document.getWindow().$.frameElement,
outer = resizeInner ? container.getChild( 1 ) : container;
// Set as border box width. (#5353)
outer.setSize( 'width', width, true );
// WebKit needs to refresh the iframe size to avoid rendering issues. (1/2) (#8348)
contentsFrame && ( contentsFrame.style.width = '1%' );
// Get the height delta between the outer table and the content area.
// If we're setting the content area's height, then we don't need the delta.
var delta = isContentHeight ? 0 : ( outer.$.offsetHeight || 0 ) - ( contents.$.clientHeight || 0 );
contents.setStyle( 'height', Math.max( height - delta, 0 ) + 'px' );
// WebKit needs to refresh the iframe size to avoid rendering issues. (2/2) (#8348)
contentsFrame && ( contentsFrame.style.width = '100%' );
// Emit a resize event.
this.fire( 'resize' );
};
/**
* Gets the element that can be freely used to check the editor size. This method
* is mainly used by the resize plugin, which adds a UI handle that can be used
* to resize the editor.
* @param {Boolean} forContents Whether to return the "contents" part of the theme instead of the container.
* @returns {CKEDITOR.dom.element} The resizable element.
* @example
*/
CKEDITOR.editor.prototype.getResizable = function( forContents )
{
return forContents ? CKEDITOR.document.getById( 'cke_contents_' + this.name ) : this.container;
};
/**
* Makes it possible to place some of the editor UI blocks, like the toolbar
* and the elements path, into any element in the page.
* The elements used to hold the UI blocks can be shared among several editor
* instances. In that case, only the blocks of the active editor instance will
* display.
* @name CKEDITOR.config.sharedSpaces
* @type Object
* @default undefined
* @example
* // Place the toolbar inside the element with ID "someElementId" and the
* // elements path into the element with ID "anotherId".
* config.sharedSpaces =
* {
* top : 'someElementId',
* bottom : 'anotherId'
* };
* @example
* // Place the toolbar inside the element with ID "someElementId". The
* // elements path will remain attached to the editor UI.
* config.sharedSpaces =
* {
* top : 'someElementId'
* };
*/
/**
* Fired after the editor instance is resized through
* the {@link CKEDITOR.editor.prototype.resize} method.
* @name CKEDITOR.editor#resize
* @event
*/