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