1 /*
  2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5
  6 /**
  7  * @fileOverview The "toolbar" plugin. Renders the default toolbar interface in
  8  * the editor.
  9  */
 10
 11 (function()
 12 {
 13 	var toolbox = function()
 14 	{
 15 		this.toolbars = [];
 16 		this.focusCommandExecuted = false;
 17 	};
 18
 19 	toolbox.prototype.focus = function()
 20 	{
 21 		for ( var t = 0, toolbar ; toolbar = this.toolbars[ t++ ] ; )
 22 		{
 23 			for ( var i = 0, item ; item = toolbar.items[ i++ ] ; )
 24 			{
 25 				if ( item.focus )
 26 				{
 27 					item.focus();
 28 					return;
 29 				}
 30 			}
 31 		}
 32 	};
 33
 34 	var commands =
 35 	{
 36 		toolbarFocus :
 37 		{
 38 			modes : { wysiwyg : 1, source : 1 },
 39
 40 			exec : function( editor )
 41 			{
 42 				if ( editor.toolbox )
 43 				{
 44 					editor.toolbox.focusCommandExecuted = true;
 45
 46 					// Make the first button focus accessible. (#3417)
 47 					if ( CKEDITOR.env.ie )
 48 						setTimeout( function(){ editor.toolbox.focus(); }, 100 );
 49 					else
 50 						editor.toolbox.focus();
 51 				}
 52 			}
 53 		}
 54 	};
 55
 56 	CKEDITOR.plugins.add( 'toolbar',
 57 	{
 58 		init : function( editor )
 59 		{
 60 			var itemKeystroke = function( item, keystroke )
 61 			{
 62 				switch ( keystroke )
 63 				{
 64 					case 39 :					// RIGHT-ARROW
 65 					case 9 :					// TAB
 66 						// Look for the next item in the toolbar.
 67 						while ( ( item = item.next || ( item.toolbar.next && item.toolbar.next.items[ 0 ] ) ) && !item.focus )
 68 						{ /*jsl:pass*/ }
 69
 70 						// If available, just focus it, otherwise focus the
 71 						// first one.
 72 						if ( item )
 73 							item.focus();
 74 						else
 75 							editor.toolbox.focus();
 76
 77 						return false;
 78
 79 					case 37 :					// LEFT-ARROW
 80 					case CKEDITOR.SHIFT + 9 :	// SHIFT + TAB
 81 						// Look for the previous item in the toolbar.
 82 						while ( ( item = item.previous || ( item.toolbar.previous && item.toolbar.previous.items[ item.toolbar.previous.items.length - 1 ] ) ) && !item.focus )
 83 						{ /*jsl:pass*/ }
 84
 85 						// If available, just focus it, otherwise focus the
 86 						// last one.
 87 						if ( item )
 88 							item.focus();
 89 						else
 90 						{
 91 							var lastToolbarItems = editor.toolbox.toolbars[ editor.toolbox.toolbars.length - 1 ].items;
 92 							lastToolbarItems[ lastToolbarItems.length - 1 ].focus();
 93 						}
 94
 95 						return false;
 96
 97 					case 27 :					// ESC
 98 						editor.focus();
 99 						return false;
100
101 					case 13 :					// ENTER
102 					case 32 :					// SPACE
103 						item.execute();
104 						return false;
105 				}
106 				return true;
107 			};
108
109 			editor.on( 'themeSpace', function( event )
110 				{
111 					if ( event.data.space == editor.config.toolbarLocation )
112 					{
113 						editor.toolbox = new toolbox();
114
115 						var output = [ '<div class="cke_toolbox"' ],
116 							expanded =  editor.config.toolbarStartupExpanded,
117 							groupStarted;
118
119 						output.push( expanded ? '>' : ' style="display:none">' );
120
121 						var toolbars = editor.toolbox.toolbars,
122 							toolbar =
123 									( editor.config.toolbar instanceof Array ) ?
124 										editor.config.toolbar
125 									:
126 										editor.config[ 'toolbar_' + editor.config.toolbar ];
127
128 						for ( var r = 0 ; r < toolbar.length ; r++ )
129 						{
130 							var row = toolbar[ r ],
131 								toolbarId = 'cke_' + CKEDITOR.tools.getNextNumber(),
132 								toolbarObj = { id : toolbarId, items : [] };
133
134 							if ( groupStarted )
135 							{
136 								output.push( '</div>' );
137 								groupStarted = 0;
138 							}
139
140 							if ( row === '/' )
141 							{
142 								output.push( '<div class="cke_break"></div>' );
143 								continue;
144 							}
145
146 							output.push( '<span id="', toolbarId, '" class="cke_toolbar"><span class="cke_toolbar_start"></span>' );
147
148 							// Add the toolbar to the "editor.toolbox.toolbars"
149 							// array.
150 							var index = toolbars.push( toolbarObj ) - 1;
151
152 							// Create the next/previous reference.
153 							if ( index > 0 )
154 							{
155 								toolbarObj.previous = toolbars[ index - 1 ];
156 								toolbarObj.previous.next = toolbarObj;
157 							}
158
159 							// Create all items defined for this toolbar.
160 							for ( var i = 0 ; i < row.length ; i++ )
161 							{
162 								var item,
163 									itemName = row[ i ];
164
165 								if ( itemName == '-' )
166 									item = CKEDITOR.ui.separator;
167 								else
168 									item = editor.ui.create( itemName );
169
170 								if ( item )
171 								{
172 									if ( item.canGroup )
173 									{
174 										if ( !groupStarted )
175 										{
176 											output.push( '<span class="cke_toolgroup">' );
177 											groupStarted = 1;
178 										}
179 									}
180 									else if ( groupStarted )
181 									{
182 										output.push( '</span>' );
183 										groupStarted = 0;
184 									}
185
186 									var itemObj = item.render( editor, output );
187 									index = toolbarObj.items.push( itemObj ) - 1;
188
189 									if ( index > 0 )
190 									{
191 										itemObj.previous = toolbarObj.items[ index - 1 ];
192 										itemObj.previous.next = itemObj;
193 									}
194
195 									itemObj.toolbar = toolbarObj;
196 									itemObj.onkey = itemKeystroke;
197
198 									/*
199 									 * Fix for #3052:
200 									 * Prevent JAWS from focusing the toolbar after document load.
201 									 */
202 									itemObj.onfocus = function()
203 									{
204 										if ( !editor.toolbox.focusCommandExecuted )
205 											editor.focus();
206 									};
207 								}
208 							}
209
210 							if ( groupStarted )
211 							{
212 								output.push( '</span>' );
213 								groupStarted = 0;
214 							}
215
216 							output.push( '<span class="cke_toolbar_end"></span></span>' );
217 						}
218
219 						output.push( '</div>' );
220
221 						if ( editor.config.toolbarCanCollapse )
222 						{
223 							var collapserFn = CKEDITOR.tools.addFunction(
224 								function()
225 								{
226 									editor.execCommand( 'toolbarCollapse' );
227 								} );
228
229 							var collapserId = 'cke_' + CKEDITOR.tools.getNextNumber();
230
231 							editor.addCommand( 'toolbarCollapse',
232 								{
233 									exec : function( editor )
234 									{
235 										var collapser = CKEDITOR.document.getById( collapserId );
236 										var toolbox = collapser.getPrevious();
237 										var contents = editor.getThemeSpace( 'contents' );
238 										var toolboxContainer = toolbox.getParent();
239 										var contentHeight = parseInt( contents.$.style.height, 10 );
240 										var previousHeight = toolboxContainer.$.offsetHeight;
241
242 										if ( toolbox.isVisible() )
243 										{
244 											toolbox.hide();
245 											collapser.addClass( 'cke_toolbox_collapser_min' );
246 										}
247 										else
248 										{
249 											toolbox.show();
250 											collapser.removeClass( 'cke_toolbox_collapser_min' );
251 										}
252
253 										var dy = toolboxContainer.$.offsetHeight - previousHeight;
254 										contents.setStyle( 'height', ( contentHeight - dy ) + 'px' );
255 									},
256
257 									modes : { wysiwyg : 1, source : 1 }
258 								} );
259
260 							output.push( '<a id="' + collapserId + '" class="cke_toolbox_collapser' );
261
262 							if ( !expanded )
263 								output.push( ' cke_toolbox_collapser_min' );
264
265 							output.push( '" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')"></a>' );
266 						}
267
268 						event.data.html += output.join( '' );
269 					}
270 				});
271
272 			editor.addCommand( 'toolbarFocus', commands.toolbarFocus );
273 		}
274 	});
275 })();
276
277 /**
278  * The UI element that renders a toolbar separator.
279  * @type Object
280  * @example
281  */
282 CKEDITOR.ui.separator =
283 {
284 	render : function( editor, output )
285 	{
286 		output.push( '<span class="cke_separator"></span>' );
287 		return {};
288 	}
289 };
290
291 /**
292  * The "theme space" to which rendering the toolbar. For the default theme,
293  * the recommended options are "top" and "bottom".
294  * @type String
295  * @default 'top'
296  * @see CKEDITOR.config.theme
297  * @example
298  * config.toolbarLocation = 'bottom';
299  */
300 CKEDITOR.config.toolbarLocation = 'top';
301
302 /**
303  * The toolbar definition. It is an array of toolbars (strips),
304  * each one being also an array, containing a list of UI items.
305  * @type Array
306  * @example
307  * // Defines a toolbar with only one strip containing the "Source" button, a
308  * // separator and the "Bold" and "Italic" buttons.
309  * <b>CKEDITOR.config.toolbar_Basic =
310  * [
311  *     [ 'Source', '-', 'Bold', 'Italic' ]
312  * ]</b>;
313  */
314 CKEDITOR.config.toolbar_Basic =
315 [
316 	['Bold', 'Italic', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink','-','About']
317 ];
318
319 CKEDITOR.config.toolbar_Full =
320 [
321 	['Source','-','Save','NewPage','Preview','-','Templates'],
322 	['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
323 	['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
324 	['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
325 	'/',
326 	['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
327 	['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
328 	['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
329 	['Link','Unlink','Anchor'],	['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
330 	'/',
331 	['Styles','Format','Font','FontSize'],
332 	['TextColor','BGColor'],
333 	['Maximize', 'ShowBlocks','-','About']
334 ];
335
336 /**
337  * The toolbox (alias toolbar) definition. It is a toolbar name or an array of toolbars (strips),
338  * each one being also an array, containing a list of UI items.
339  * @type Array or String
340  * @example
341  * // Defines a toolbar with only one strip containing the "Source" button, a
342  * // separator and the "Bold" and "Italic" buttons.
343  * <b>CKEDITOR.config.toolbar =
344  * [
345  *     [ 'Source', '-', 'Bold', 'Italic' ]
346  * ]</b>;
347  * // Load toolbar_Name where Name = Basic.
348  * <b>CKEDITOR.config.toolbar = 'Basic';
349  */
350 CKEDITOR.config.toolbar = 'Full';
351
352 CKEDITOR.config.toolbarCanCollapse = true;
353 CKEDITOR.config.toolbarStartupExpanded = true;
354