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