2 Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license
\r
7 * @fileOverview The "toolbar" plugin. Renders the default toolbar interface in
\r
13 var toolbox = function()
\r
16 this.focusCommandExecuted = false;
\r
19 toolbox.prototype.focus = function()
\r
21 for ( var t = 0, toolbar ; toolbar = this.toolbars[ t++ ] ; )
\r
23 for ( var i = 0, item ; item = toolbar.items[ i++ ] ; )
\r
38 modes : { wysiwyg : 1, source : 1 },
\r
41 exec : function( editor )
\r
43 if ( editor.toolbox )
\r
45 editor.toolbox.focusCommandExecuted = true;
\r
47 // Make the first button focus accessible for IE. (#3417)
\r
48 // Adobe AIR instead need while of delay.
\r
49 if ( CKEDITOR.env.ie || CKEDITOR.env.air )
\r
50 setTimeout( function(){ editor.toolbox.focus(); }, 100 );
\r
52 editor.toolbox.focus();
\r
58 CKEDITOR.plugins.add( 'toolbar',
\r
60 requires : [ 'button' ],
\r
61 init : function( editor )
\r
65 var itemKeystroke = function( item, keystroke )
\r
68 var rtl = editor.lang.dir == 'rtl',
\r
69 toolbarGroupCycling = editor.config.toolbarGroupCycling;
\r
71 toolbarGroupCycling = toolbarGroupCycling === undefined || toolbarGroupCycling;
\r
73 switch ( keystroke )
\r
76 case CKEDITOR.SHIFT + 9 : // SHIFT + TAB
\r
77 // Cycle through the toolbars, starting from the one
\r
78 // closest to the current item.
\r
79 while ( !toolbar || !toolbar.items.length )
\r
81 toolbar = keystroke == 9 ?
\r
82 ( ( toolbar ? toolbar.next : item.toolbar.next ) || editor.toolbox.toolbars[ 0 ] ) :
\r
83 ( ( toolbar ? toolbar.previous : item.toolbar.previous ) || editor.toolbox.toolbars[ editor.toolbox.toolbars.length - 1 ] );
\r
85 // Look for the first item that accepts focus.
\r
86 if ( toolbar.items.length )
\r
88 item = toolbar.items[ endFlag ? ( toolbar.items.length - 1 ) : 0 ];
\r
89 while ( item && !item.focus )
\r
91 item = endFlag ? item.previous : item.next;
\r
104 case rtl ? 37 : 39 : // RIGHT-ARROW
\r
105 case 40 : // DOWN-ARROW
\r
109 // Look for the next item in the toolbar.
\r
112 // If it's the last item, cycle to the first one.
\r
113 if ( !next && toolbarGroupCycling )
\r
114 next = item.toolbar.items[ 0 ];
\r
116 while ( next && !next.focus )
\r
118 // If available, just focus it, otherwise focus the
\r
124 itemKeystroke( item, 9 );
\r
128 case rtl ? 39 : 37 : // LEFT-ARROW
\r
129 case 38 : // UP-ARROW
\r
133 // Look for the previous item in the toolbar.
\r
134 next = next.previous;
\r
136 // If it's the first item, cycle to the last one.
\r
137 if ( !next && toolbarGroupCycling )
\r
138 next = item.toolbar.items[ item.toolbar.items.length - 1 ];
\r
140 while ( next && !next.focus )
\r
142 // If available, just focus it, otherwise focus the
\r
149 // Send a SHIFT + TAB.
\r
150 itemKeystroke( item, CKEDITOR.SHIFT + 9 );
\r
168 editor.on( 'themeSpace', function( event )
\r
170 if ( event.data.space == editor.config.toolbarLocation )
\r
172 editor.toolbox = new toolbox();
\r
174 var labelId = CKEDITOR.tools.getNextId();
\r
176 var output = [ '<div class="cke_toolbox" role="group" aria-labelledby="', labelId, '" onmousedown="return false;"' ],
\r
177 expanded = editor.config.toolbarStartupExpanded !== false,
\r
180 output.push( expanded ? '>' : ' style="display:none">' );
\r
182 // Sends the ARIA label.
\r
183 output.push( '<span id="', labelId, '" class="cke_voice_label">', editor.lang.toolbars, '</span>' );
\r
185 var toolbars = editor.toolbox.toolbars,
\r
187 ( editor.config.toolbar instanceof Array ) ?
\r
188 editor.config.toolbar
\r
190 editor.config[ 'toolbar_' + editor.config.toolbar ];
\r
192 for ( var r = 0 ; r < toolbar.length ; r++ )
\r
197 row = toolbar[ r ],
\r
200 // It's better to check if the row object is really
\r
201 // available because it's a common mistake to leave
\r
202 // an extra comma in the toolbar definition
\r
203 // settings, which leads on the editor not loading
\r
204 // at all in IE. (#3983)
\r
208 if ( groupStarted )
\r
210 output.push( '</div>' );
\r
216 output.push( '<div class="cke_break"></div>' );
\r
220 items = row.items || row;
\r
222 // Create all items defined for this toolbar.
\r
223 for ( var i = 0 ; i < items.length ; i++ )
\r
226 itemName = items[ i ],
\r
229 item = editor.ui.create( itemName );
\r
233 canGroup = item.canGroup !== false;
\r
235 // Initialize the toolbar first, if needed.
\r
238 // Create the basic toolbar object.
\r
239 toolbarId = CKEDITOR.tools.getNextId();
\r
240 toolbarObj = { id : toolbarId, items : [] };
\r
241 toolbarName = row.name && ( editor.lang.toolbarGroups[ row.name ] || row.name );
\r
243 // Output the toolbar opener.
\r
244 output.push( '<span id="', toolbarId, '" class="cke_toolbar"',
\r
245 ( toolbarName ? ' aria-labelledby="'+ toolbarId + '_label"' : '' ),
\r
246 ' role="toolbar">' );
\r
248 // If a toolbar name is available, send the voice label.
\r
249 toolbarName && output.push( '<span id="', toolbarId, '_label" class="cke_voice_label">', toolbarName, '</span>' );
\r
251 output.push( '<span class="cke_toolbar_start"></span>' );
\r
253 // Add the toolbar to the "editor.toolbox.toolbars"
\r
255 var index = toolbars.push( toolbarObj ) - 1;
\r
257 // Create the next/previous reference.
\r
260 toolbarObj.previous = toolbars[ index - 1 ];
\r
261 toolbarObj.previous.next = toolbarObj;
\r
267 if ( !groupStarted )
\r
269 output.push( '<span class="cke_toolgroup" role="presentation">' );
\r
273 else if ( groupStarted )
\r
275 output.push( '</span>' );
\r
279 var itemObj = item.render( editor, output );
\r
280 index = toolbarObj.items.push( itemObj ) - 1;
\r
284 itemObj.previous = toolbarObj.items[ index - 1 ];
\r
285 itemObj.previous.next = itemObj;
\r
288 itemObj.toolbar = toolbarObj;
\r
289 itemObj.onkey = itemKeystroke;
\r
293 * Prevent JAWS from focusing the toolbar after document load.
\r
295 itemObj.onfocus = function()
\r
297 if ( !editor.toolbox.focusCommandExecuted )
\r
303 if ( groupStarted )
\r
305 output.push( '</span>' );
\r
310 output.push( '<span class="cke_toolbar_end"></span></span>' );
\r
313 output.push( '</div>' );
\r
315 if ( editor.config.toolbarCanCollapse )
\r
317 var collapserFn = CKEDITOR.tools.addFunction(
\r
320 editor.execCommand( 'toolbarCollapse' );
\r
323 editor.on( 'destroy', function () {
\r
324 CKEDITOR.tools.removeFunction( collapserFn );
\r
327 var collapserId = CKEDITOR.tools.getNextId();
\r
329 editor.addCommand( 'toolbarCollapse',
\r
332 exec : function( editor )
\r
334 var collapser = CKEDITOR.document.getById( collapserId ),
\r
335 toolbox = collapser.getPrevious(),
\r
336 contents = editor.getThemeSpace( 'contents' ),
\r
337 toolboxContainer = toolbox.getParent(),
\r
338 contentHeight = parseInt( contents.$.style.height, 10 ),
\r
339 previousHeight = toolboxContainer.$.offsetHeight,
\r
340 collapsed = !toolbox.isVisible();
\r
345 collapser.addClass( 'cke_toolbox_collapser_min' );
\r
346 collapser.setAttribute( 'title', editor.lang.toolbarExpand );
\r
351 collapser.removeClass( 'cke_toolbox_collapser_min' );
\r
352 collapser.setAttribute( 'title', editor.lang.toolbarCollapse );
\r
355 // Update collapser symbol.
\r
356 collapser.getFirst().setText( collapsed ?
\r
357 '\u25B2' : // BLACK UP-POINTING TRIANGLE
\r
358 '\u25C0' ); // BLACK LEFT-POINTING TRIANGLE
\r
360 var dy = toolboxContainer.$.offsetHeight - previousHeight;
\r
361 contents.setStyle( 'height', ( contentHeight - dy ) + 'px' );
\r
363 editor.fire( 'resize' );
\r
366 modes : { wysiwyg : 1, source : 1 }
\r
369 output.push( '<a title="' + ( expanded ? editor.lang.toolbarCollapse : editor.lang.toolbarExpand )
\r
370 + '" id="' + collapserId + '" tabIndex="-1" class="cke_toolbox_collapser' );
\r
373 output.push( ' cke_toolbox_collapser_min' );
\r
375 output.push( '" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')">',
\r
376 '<span>▲</span>', // BLACK UP-POINTING TRIANGLE
\r
380 event.data.html += output.join( '' );
\r
384 editor.on( 'destroy', function()
\r
386 var toolbars, index = 0, i,
\r
388 toolbars = this.toolbox.toolbars;
\r
389 for ( ; index < toolbars.length; index++ )
\r
391 items = toolbars[ index ].items;
\r
392 for ( i = 0; i < items.length; i++ )
\r
394 instance = items[ i ];
\r
395 if ( instance.clickFn ) CKEDITOR.tools.removeFunction( instance.clickFn );
\r
396 if ( instance.keyDownFn ) CKEDITOR.tools.removeFunction( instance.keyDownFn );
\r
401 editor.addCommand( 'toolbarFocus', commands.toolbarFocus );
\r
403 editor.ui.add( '-', CKEDITOR.UI_SEPARATOR, {} );
\r
404 editor.ui.addHandler( CKEDITOR.UI_SEPARATOR,
\r
409 render : function( editor, output )
\r
411 output.push( '<span class="cke_separator" role="separator"></span>' );
\r
421 CKEDITOR.UI_SEPARATOR = 'separator';
\r
424 * The "theme space" to which rendering the toolbar. For the default theme,
\r
425 * the recommended options are "top" and "bottom".
\r
428 * @see CKEDITOR.config.theme
\r
430 * config.toolbarLocation = 'bottom';
\r
432 CKEDITOR.config.toolbarLocation = 'top';
\r
435 * The toolbar definition. It is an array of toolbars (strips),
\r
436 * each one being also an array, containing a list of UI items.
\r
437 * Note that this setting is composed by "toolbar_" added by the toolbar name,
\r
438 * which in this case is called "Basic". This second part of the setting name
\r
439 * can be anything. You must use this name in the
\r
440 * {@link CKEDITOR.config.toolbar} setting, so you instruct the editor which
\r
441 * toolbar_(name) setting to you.
\r
444 * // Defines a toolbar with only one strip containing the "Source" button, a
\r
445 * // separator and the "Bold" and "Italic" buttons.
\r
446 * <b>config.toolbar_Basic =
\r
448 * [ 'Source', '-', 'Bold', 'Italic' ]
\r
450 * config.toolbar = 'Basic';
\r
452 CKEDITOR.config.toolbar_Basic =
\r
454 ['Bold', 'Italic', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink','-','About']
\r
458 * This is the default toolbar definition used by the editor. It contains all
\r
461 * @default (see example)
\r
463 * // This is actually the default value.
\r
464 * config.toolbar_Full =
\r
466 * { name: 'document', items : [ 'Source','-','Save','NewPage','DocProps','Preview','Print','-','Templates' ] },
\r
467 * { name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },
\r
468 * { name: 'editing', items : [ 'Find','Replace','-','SelectAll','-','SpellChecker', 'Scayt' ] },
\r
469 * { name: 'forms', items : [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
\r
471 * { name: 'basicstyles', items : [ 'Bold','Italic','Underline','Strike','Subscript','Superscript','-','RemoveFormat' ] },
\r
472 * { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','BidiLtr','BidiRtl' ] },
\r
473 * { name: 'links', items : [ 'Link','Unlink','Anchor' ] },
\r
474 * { name: 'insert', items : [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak' ] },
\r
476 * { name: 'styles', items : [ 'Styles','Format','Font','FontSize' ] },
\r
477 * { name: 'colors', items : [ 'TextColor','BGColor' ] },
\r
478 * { name: 'tools', items : [ 'Maximize', 'ShowBlocks','-','About' ] }
\r
481 CKEDITOR.config.toolbar_Full =
\r
483 { name: 'document', items : [ 'Source','-','Save','NewPage','DocProps','Preview','Print','-','Templates' ] },
\r
484 { name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },
\r
485 { name: 'editing', items : [ 'Find','Replace','-','SelectAll','-','SpellChecker', 'Scayt' ] },
\r
486 { name: 'forms', items : [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
\r
488 { name: 'basicstyles', items : [ 'Bold','Italic','Underline','Strike','Subscript','Superscript','-','RemoveFormat' ] },
\r
489 { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','BidiLtr','BidiRtl' ] },
\r
490 { name: 'links', items : [ 'Link','Unlink','Anchor' ] },
\r
491 { name: 'insert', items : [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak','Iframe' ] },
\r
493 { name: 'styles', items : [ 'Styles','Format','Font','FontSize' ] },
\r
494 { name: 'colors', items : [ 'TextColor','BGColor' ] },
\r
495 { name: 'tools', items : [ 'Maximize', 'ShowBlocks','-','About' ] }
\r
499 * The toolbox (alias toolbar) definition. It is a toolbar name or an array of
\r
500 * toolbars (strips), each one being also an array, containing a list of UI items.
\r
501 * @type Array|String
\r
504 * // Defines a toolbar with only one strip containing the "Source" button, a
\r
505 * // separator and the "Bold" and "Italic" buttons.
\r
508 * [ 'Source', '-', 'Bold', 'Italic' ]
\r
511 * // Load toolbar_Name where Name = Basic.
\r
512 * config.toolbar = 'Basic';
\r
514 CKEDITOR.config.toolbar = 'Full';
\r
517 * Whether the toolbar can be collapsed by the user. If disabled, the collapser
\r
518 * button will not be displayed.
\r
522 * config.toolbarCanCollapse = false;
\r
524 CKEDITOR.config.toolbarCanCollapse = true;
\r
527 * Whether the toolbar must start expanded when the editor is loaded.
\r
528 * @name CKEDITOR.config.toolbarStartupExpanded
\r
532 * config.toolbarStartupExpanded = false;
\r
536 * When enabled, makes the arrow keys navigation cycle within the current
\r
537 * toolbar group. Otherwise the arrows will move trought all items available in
\r
538 * the toolbar. The TAB key will still be used to quickly jump among the
\r
540 * @name CKEDITOR.config.toolbarGroupCycling
\r
545 * config.toolbarGroupCycling = false;
\r