JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.2
[ckeditor.git] / _source / plugins / toolbar / plugin.js
1 /*\r
2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 /**\r
7  * @fileOverview The "toolbar" plugin. Renders the default toolbar interface in\r
8  * the editor.\r
9  */\r
10 \r
11 (function()\r
12 {\r
13         var toolbox = function()\r
14         {\r
15                 this.toolbars = [];\r
16                 this.focusCommandExecuted = false;\r
17         };\r
18 \r
19         toolbox.prototype.focus = function()\r
20         {\r
21                 for ( var t = 0, toolbar ; toolbar = this.toolbars[ t++ ] ; )\r
22                 {\r
23                         for ( var i = 0, item ; item = toolbar.items[ i++ ] ; )\r
24                         {\r
25                                 if ( item.focus )\r
26                                 {\r
27                                         item.focus();\r
28                                         return;\r
29                                 }\r
30                         }\r
31                 }\r
32         };\r
33 \r
34         var commands =\r
35         {\r
36                 toolbarFocus :\r
37                 {\r
38                         modes : { wysiwyg : 1, source : 1 },\r
39 \r
40                         exec : function( editor )\r
41                         {\r
42                                 if ( editor.toolbox )\r
43                                 {\r
44                                         editor.toolbox.focusCommandExecuted = true;\r
45 \r
46                                         // Make the first button focus accessible. (#3417)\r
47                                         if ( CKEDITOR.env.ie )\r
48                                                 setTimeout( function(){ editor.toolbox.focus(); }, 100 );\r
49                                         else\r
50                                                 editor.toolbox.focus();\r
51                                 }\r
52                         }\r
53                 }\r
54         };\r
55 \r
56         CKEDITOR.plugins.add( 'toolbar',\r
57         {\r
58                 init : function( editor )\r
59                 {\r
60                         var itemKeystroke = function( item, keystroke )\r
61                         {\r
62                                 var next, nextToolGroup, groupItemsCount;\r
63 \r
64                                 switch ( keystroke )\r
65                                 {\r
66                                         case 39 :                                       // RIGHT-ARROW\r
67                                         case 9 :                                        // TAB\r
68                                                 do\r
69                                                 {\r
70                                                         // Look for the previous item in the toolbar.\r
71                                                         next = item.next;\r
72 \r
73                                                         if ( !next )\r
74                                                         {\r
75                                                                 nextToolGroup = item.toolbar.next;\r
76                                                                 groupItemsCount = nextToolGroup && nextToolGroup.items.length;\r
77 \r
78                                                                 // Bypass the empty toolgroups.\r
79                                                                 while ( groupItemsCount === 0 )\r
80                                                                 {\r
81                                                                         nextToolGroup = nextToolGroup.next;\r
82                                                                         groupItemsCount = nextToolGroup && nextToolGroup.items.length;\r
83                                                                 }\r
84 \r
85                                                                 if ( nextToolGroup )\r
86                                                                         next = nextToolGroup.items[ 0 ];\r
87                                                         }\r
88 \r
89                                                         item = next;\r
90                                                 }\r
91                                                 while ( item && !item.focus )\r
92 \r
93                                                 // If available, just focus it, otherwise focus the\r
94                                                 // first one.\r
95                                                 if ( item )\r
96                                                         item.focus();\r
97                                                 else\r
98                                                         editor.toolbox.focus();\r
99 \r
100                                                 return false;\r
101 \r
102                                         case 37 :                                       // LEFT-ARROW\r
103                                         case CKEDITOR.SHIFT + 9 :       // SHIFT + TAB\r
104                                                 do\r
105                                                 {\r
106                                                         // Look for the previous item in the toolbar.\r
107                                                         next = item.previous;\r
108 \r
109                                                         if ( !next )\r
110                                                         {\r
111                                                                 nextToolGroup = item.toolbar.previous;\r
112                                                                 groupItemsCount = nextToolGroup && nextToolGroup.items.length;\r
113 \r
114                                                                 // Bypass the empty toolgroups.\r
115                                                                 while ( groupItemsCount === 0 )\r
116                                                                 {\r
117                                                                         nextToolGroup = nextToolGroup.previous;\r
118                                                                         groupItemsCount = nextToolGroup && nextToolGroup.items.length;\r
119                                                                 }\r
120 \r
121                                                                 if ( nextToolGroup )\r
122                                                                         next = nextToolGroup.items[ groupItemsCount - 1 ];\r
123                                                         }\r
124 \r
125                                                         item = next;\r
126                                                 }\r
127                                                 while ( item && !item.focus )\r
128 \r
129                                                 // If available, just focus it, otherwise focus the\r
130                                                 // last one.\r
131                                                 if ( item )\r
132                                                         item.focus();\r
133                                                 else\r
134                                                 {\r
135                                                         var lastToolbarItems = editor.toolbox.toolbars[ editor.toolbox.toolbars.length - 1 ].items;\r
136                                                         lastToolbarItems[ lastToolbarItems.length - 1 ].focus();\r
137                                                 }\r
138 \r
139                                                 return false;\r
140 \r
141                                         case 27 :                                       // ESC\r
142                                                 editor.focus();\r
143                                                 return false;\r
144 \r
145                                         case 13 :                                       // ENTER\r
146                                         case 32 :                                       // SPACE\r
147                                                 item.execute();\r
148                                                 return false;\r
149                                 }\r
150                                 return true;\r
151                         };\r
152 \r
153                         editor.on( 'themeSpace', function( event )\r
154                                 {\r
155                                         if ( event.data.space == editor.config.toolbarLocation )\r
156                                         {\r
157                                                 editor.toolbox = new toolbox();\r
158 \r
159                                                 var labelId = 'cke_' + CKEDITOR.tools.getNextNumber();\r
160 \r
161                                                 var output = [ '<div class="cke_toolbox" role="toolbar" aria-labelledby="', labelId, '"' ],\r
162                                                         expanded =  editor.config.toolbarStartupExpanded !== false,\r
163                                                         groupStarted;\r
164 \r
165                                                 output.push( expanded ? '>' : ' style="display:none">' );\r
166 \r
167                                                 // Sends the ARIA label.\r
168                                                 output.push( '<span id="', labelId, '" class="cke_voice_label">', editor.lang.toolbar, '</span>' );\r
169 \r
170                                                 var toolbars = editor.toolbox.toolbars,\r
171                                                         toolbar =\r
172                                                                         ( editor.config.toolbar instanceof Array ) ?\r
173                                                                                 editor.config.toolbar\r
174                                                                         :\r
175                                                                                 editor.config[ 'toolbar_' + editor.config.toolbar ];\r
176 \r
177                                                 for ( var r = 0 ; r < toolbar.length ; r++ )\r
178                                                 {\r
179                                                         var row = toolbar[ r ];\r
180 \r
181                                                         // It's better to check if the row object is really\r
182                                                         // available because it's a common mistake to leave\r
183                                                         // an extra comma in the toolbar definition\r
184                                                         // settings, which leads on the editor not loading\r
185                                                         // at all in IE. (#3983)\r
186                                                         if ( !row )\r
187                                                                 continue;\r
188 \r
189                                                         var toolbarId = 'cke_' + CKEDITOR.tools.getNextNumber(),\r
190                                                                 toolbarObj = { id : toolbarId, items : [] };\r
191 \r
192                                                         if ( groupStarted )\r
193                                                         {\r
194                                                                 output.push( '</div>' );\r
195                                                                 groupStarted = 0;\r
196                                                         }\r
197 \r
198                                                         if ( row === '/' )\r
199                                                         {\r
200                                                                 output.push( '<div class="cke_break"></div>' );\r
201                                                                 continue;\r
202                                                         }\r
203 \r
204                                                         output.push( '<span id="', toolbarId, '" class="cke_toolbar" role="presentation"><span class="cke_toolbar_start"></span>' );\r
205 \r
206                                                         // Add the toolbar to the "editor.toolbox.toolbars"\r
207                                                         // array.\r
208                                                         var index = toolbars.push( toolbarObj ) - 1;\r
209 \r
210                                                         // Create the next/previous reference.\r
211                                                         if ( index > 0 )\r
212                                                         {\r
213                                                                 toolbarObj.previous = toolbars[ index - 1 ];\r
214                                                                 toolbarObj.previous.next = toolbarObj;\r
215                                                         }\r
216 \r
217                                                         // Create all items defined for this toolbar.\r
218                                                         for ( var i = 0 ; i < row.length ; i++ )\r
219                                                         {\r
220                                                                 var item,\r
221                                                                         itemName = row[ i ];\r
222 \r
223                                                                 if ( itemName == '-' )\r
224                                                                         item = CKEDITOR.ui.separator;\r
225                                                                 else\r
226                                                                         item = editor.ui.create( itemName );\r
227 \r
228                                                                 if ( item )\r
229                                                                 {\r
230                                                                         if ( item.canGroup )\r
231                                                                         {\r
232                                                                                 if ( !groupStarted )\r
233                                                                                 {\r
234                                                                                         output.push( '<span class="cke_toolgroup" role="presentation">' );\r
235                                                                                         groupStarted = 1;\r
236                                                                                 }\r
237                                                                         }\r
238                                                                         else if ( groupStarted )\r
239                                                                         {\r
240                                                                                 output.push( '</span>' );\r
241                                                                                 groupStarted = 0;\r
242                                                                         }\r
243 \r
244                                                                         var itemObj = item.render( editor, output );\r
245                                                                         index = toolbarObj.items.push( itemObj ) - 1;\r
246 \r
247                                                                         if ( index > 0 )\r
248                                                                         {\r
249                                                                                 itemObj.previous = toolbarObj.items[ index - 1 ];\r
250                                                                                 itemObj.previous.next = itemObj;\r
251                                                                         }\r
252 \r
253                                                                         itemObj.toolbar = toolbarObj;\r
254                                                                         itemObj.onkey = itemKeystroke;\r
255 \r
256                                                                         /*\r
257                                                                          * Fix for #3052:\r
258                                                                          * Prevent JAWS from focusing the toolbar after document load.\r
259                                                                          */\r
260                                                                         itemObj.onfocus = function()\r
261                                                                         {\r
262                                                                                 if ( !editor.toolbox.focusCommandExecuted )\r
263                                                                                         editor.focus();\r
264                                                                         };\r
265                                                                 }\r
266                                                         }\r
267 \r
268                                                         if ( groupStarted )\r
269                                                         {\r
270                                                                 output.push( '</span>' );\r
271                                                                 groupStarted = 0;\r
272                                                         }\r
273 \r
274                                                         output.push( '<span class="cke_toolbar_end"></span></span>' );\r
275                                                 }\r
276 \r
277                                                 output.push( '</div>' );\r
278 \r
279                                                 if ( editor.config.toolbarCanCollapse )\r
280                                                 {\r
281                                                         var collapserFn = CKEDITOR.tools.addFunction(\r
282                                                                 function()\r
283                                                                 {\r
284                                                                         editor.execCommand( 'toolbarCollapse' );\r
285                                                                 } );\r
286 \r
287                                                         var collapserId = 'cke_' + CKEDITOR.tools.getNextNumber();\r
288 \r
289                                                         editor.addCommand( 'toolbarCollapse',\r
290                                                                 {\r
291                                                                         exec : function( editor )\r
292                                                                         {\r
293                                                                                 var collapser = CKEDITOR.document.getById( collapserId );\r
294                                                                                 var toolbox = collapser.getPrevious();\r
295                                                                                 var contents = editor.getThemeSpace( 'contents' );\r
296                                                                                 var toolboxContainer = toolbox.getParent();\r
297                                                                                 var contentHeight = parseInt( contents.$.style.height, 10 );\r
298                                                                                 var previousHeight = toolboxContainer.$.offsetHeight;\r
299                                                                                 var collapsed = !toolbox.isVisible();\r
300 \r
301                                                                                 if ( !collapsed )\r
302                                                                                 {\r
303                                                                                         toolbox.hide();\r
304                                                                                         collapser.addClass( 'cke_toolbox_collapser_min' );\r
305                                                                                         collapser.setAttribute( 'title', editor.lang.toolbarExpand );\r
306                                                                                 }\r
307                                                                                 else\r
308                                                                                 {\r
309                                                                                         toolbox.show();\r
310                                                                                         collapser.removeClass( 'cke_toolbox_collapser_min' );\r
311                                                                                         collapser.setAttribute( 'title', editor.lang.toolbarCollapse );\r
312                                                                                 }\r
313 \r
314                                                                                 // Update collapser symbol.\r
315                                                                                 collapser.getFirst().setText( collapsed ?\r
316                                                                                         '\u25B2' :              // BLACK UP-POINTING TRIANGLE\r
317                                                                                         '\u25C0' );             // BLACK LEFT-POINTING TRIANGLE\r
318 \r
319                                                                                 var dy = toolboxContainer.$.offsetHeight - previousHeight;\r
320                                                                                 contents.setStyle( 'height', ( contentHeight - dy ) + 'px' );\r
321 \r
322                                                                                 editor.fire( 'resize' );\r
323                                                                         },\r
324 \r
325                                                                         modes : { wysiwyg : 1, source : 1 }\r
326                                                                 } );\r
327 \r
328                                                         output.push( '<a title="' + ( expanded ? editor.lang.toolbarCollapse : editor.lang.toolbarExpand )\r
329                                                                                                           + '" id="' + collapserId + '" tabIndex="-1" class="cke_toolbox_collapser' );\r
330 \r
331                                                         if ( !expanded )\r
332                                                                 output.push( ' cke_toolbox_collapser_min' );\r
333 \r
334                                                         output.push( '" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')">',\r
335                                                                                 '<span>&#9650;</span>',         // BLACK UP-POINTING TRIANGLE\r
336                                                                                 '</a>' );\r
337                                                 }\r
338 \r
339                                                 event.data.html += output.join( '' );\r
340                                         }\r
341                                 });\r
342 \r
343                         editor.addCommand( 'toolbarFocus', commands.toolbarFocus );\r
344                 }\r
345         });\r
346 })();\r
347 \r
348 /**\r
349  * The UI element that renders a toolbar separator.\r
350  * @type Object\r
351  * @example\r
352  */\r
353 CKEDITOR.ui.separator =\r
354 {\r
355         render : function( editor, output )\r
356         {\r
357                 output.push( '<span class="cke_separator" role="separator"></span>' );\r
358                 return {};\r
359         }\r
360 };\r
361 \r
362 /**\r
363  * The "theme space" to which rendering the toolbar. For the default theme,\r
364  * the recommended options are "top" and "bottom".\r
365  * @type String\r
366  * @default 'top'\r
367  * @see CKEDITOR.config.theme\r
368  * @example\r
369  * config.toolbarLocation = 'bottom';\r
370  */\r
371 CKEDITOR.config.toolbarLocation = 'top';\r
372 \r
373 /**\r
374  * The toolbar definition. It is an array of toolbars (strips),\r
375  * each one being also an array, containing a list of UI items.\r
376  * Note that this setting is composed by "toolbar_" added by the toolbar name,\r
377  * which in this case is called "Basic". This second part of the setting name\r
378  * can be anything. You must use this name in the\r
379  * {@link CKEDITOR.config.toolbar} setting, so you instruct the editor which\r
380  * toolbar_(name) setting to you.\r
381  * @type Array\r
382  * @example\r
383  * // Defines a toolbar with only one strip containing the "Source" button, a\r
384  * // separator and the "Bold" and "Italic" buttons.\r
385  * <b>config.toolbar_Basic =\r
386  * [\r
387  *     [ 'Source', '-', 'Bold', 'Italic' ]\r
388  * ]</b>;\r
389  * config.toolbar = 'Basic';\r
390  */\r
391 CKEDITOR.config.toolbar_Basic =\r
392 [\r
393         ['Bold', 'Italic', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink','-','About']\r
394 ];\r
395 \r
396 /**\r
397  * This is the default toolbar definition used by the editor. It contains all\r
398  * editor features.\r
399  * @type Array\r
400  * @default (see example)\r
401  * @example\r
402  * // This is actually the default value.\r
403  * config.toolbar_Full =\r
404  * [\r
405  *     ['Source','-','Save','NewPage','Preview','-','Templates'],\r
406  *     ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],\r
407  *     ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],\r
408  *     ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],\r
409  *     '/',\r
410  *     ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],\r
411  *     ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],\r
412  *     ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],\r
413  *     ['Link','Unlink','Anchor'],\r
414  *     ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],\r
415  *     '/',\r
416  *     ['Styles','Format','Font','FontSize'],\r
417  *     ['TextColor','BGColor'],\r
418  *     ['Maximize', 'ShowBlocks','-','About']\r
419  * ];\r
420  */\r
421 CKEDITOR.config.toolbar_Full =\r
422 [\r
423         ['Source','-','Save','NewPage','Preview','-','Templates'],\r
424         ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],\r
425         ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],\r
426         ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],\r
427         '/',\r
428         ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],\r
429         ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],\r
430         ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],\r
431         ['Link','Unlink','Anchor'],\r
432         ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],\r
433         '/',\r
434         ['Styles','Format','Font','FontSize'],\r
435         ['TextColor','BGColor'],\r
436         ['Maximize', 'ShowBlocks','-','About']\r
437 ];\r
438 \r
439 /**\r
440  * The toolbox (alias toolbar) definition. It is a toolbar name or an array of\r
441  * toolbars (strips), each one being also an array, containing a list of UI items.\r
442  * @type Array|String\r
443  * @default 'Full'\r
444  * @example\r
445  * // Defines a toolbar with only one strip containing the "Source" button, a\r
446  * // separator and the "Bold" and "Italic" buttons.\r
447  * config.toolbar =\r
448  * [\r
449  *     [ 'Source', '-', 'Bold', 'Italic' ]\r
450  * ];\r
451  * @example\r
452  * // Load toolbar_Name where Name = Basic.\r
453  * config.toolbar = 'Basic';\r
454  */\r
455 CKEDITOR.config.toolbar = 'Full';\r
456 \r
457 /**\r
458  * Whether the toolbar can be collapsed by the user. If disabled, the collapser\r
459  * button will not be displayed.\r
460  * @type Boolean\r
461  * @default true\r
462  * @example\r
463  * config.toolbarCanCollapse = false;\r
464  */\r
465 CKEDITOR.config.toolbarCanCollapse = true;\r
466 \r
467 /**\r
468  * Whether the toolbar must start expanded when the editor is loaded.\r
469  * @name CKEDITOR.config.toolbarStartupExpanded\r
470  * @type Boolean\r
471  * @default true\r
472  * @example\r
473  * config.toolbarStartupExpanded = false;\r
474  */\r