]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blame - sources/plugins/toolbar/plugin.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / toolbar / plugin.js
CommitLineData
c63493c8
IB
1/**\r
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\r
3 * For licensing, see LICENSE.md 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 var toolbox = function() {\r
13 this.toolbars = [];\r
14 this.focusCommandExecuted = false;\r
15 };\r
16\r
17 toolbox.prototype.focus = function() {\r
18 for ( var t = 0, toolbar; toolbar = this.toolbars[ t++ ]; ) {\r
19 for ( var i = 0, item; item = toolbar.items[ i++ ]; ) {\r
20 if ( item.focus ) {\r
21 item.focus();\r
22 return;\r
23 }\r
24 }\r
25 }\r
26 };\r
27\r
28 var commands = {\r
29 toolbarFocus: {\r
30 modes: { wysiwyg: 1, source: 1 },\r
31 readOnly: 1,\r
32\r
33 exec: function( editor ) {\r
34 if ( editor.toolbox ) {\r
35 editor.toolbox.focusCommandExecuted = true;\r
36\r
1794320d 37 // Make the first button focus accessible for IE. (http://dev.ckeditor.com/ticket/3417)\r
c63493c8
IB
38 // Adobe AIR instead need while of delay.\r
39 if ( CKEDITOR.env.ie || CKEDITOR.env.air ) {\r
40 setTimeout( function() {\r
41 editor.toolbox.focus();\r
42 }, 100 );\r
43 } else {\r
44 editor.toolbox.focus();\r
45 }\r
46 }\r
47 }\r
48 }\r
49 };\r
50\r
51 CKEDITOR.plugins.add( 'toolbar', {\r
52 requires: 'button',\r
53 // jscs:disable maximumLineLength\r
1794320d 54 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%\r
c63493c8
IB
55 // jscs:enable maximumLineLength\r
56\r
57 init: function( editor ) {\r
58 var endFlag;\r
59\r
60 var itemKeystroke = function( item, keystroke ) {\r
61 var next, toolbar;\r
62 var rtl = editor.lang.dir == 'rtl',\r
63 toolbarGroupCycling = editor.config.toolbarGroupCycling,\r
64 // Picking right/left key codes.\r
65 rightKeyCode = rtl ? 37 : 39,\r
66 leftKeyCode = rtl ? 39 : 37;\r
67\r
68 toolbarGroupCycling = toolbarGroupCycling === undefined || toolbarGroupCycling;\r
69\r
70 switch ( keystroke ) {\r
71 case 9: // TAB\r
72 case CKEDITOR.SHIFT + 9: // SHIFT + TAB\r
73 // Cycle through the toolbars, starting from the one\r
74 // closest to the current item.\r
75 while ( !toolbar || !toolbar.items.length ) {\r
76 if ( keystroke == 9 ) {\r
77 toolbar = ( ( toolbar ? toolbar.next : item.toolbar.next ) || editor.toolbox.toolbars[ 0 ] );\r
78 } else {\r
79 toolbar = ( ( toolbar ? toolbar.previous : item.toolbar.previous ) || editor.toolbox.toolbars[ editor.toolbox.toolbars.length - 1 ] );\r
80 }\r
81\r
82 // Look for the first item that accepts focus.\r
83 if ( toolbar.items.length ) {\r
84 item = toolbar.items[ endFlag ? ( toolbar.items.length - 1 ) : 0 ];\r
85 while ( item && !item.focus ) {\r
86 item = endFlag ? item.previous : item.next;\r
87\r
88 if ( !item )\r
89 toolbar = 0;\r
90 }\r
91 }\r
92 }\r
93\r
94 if ( item )\r
95 item.focus();\r
96\r
97 return false;\r
98\r
99 case rightKeyCode:\r
100 next = item;\r
101 do {\r
102 // Look for the next item in the toolbar.\r
103 next = next.next;\r
104\r
105 // If it's the last item, cycle to the first one.\r
106 if ( !next && toolbarGroupCycling ) next = item.toolbar.items[ 0 ];\r
107 }\r
108 while ( next && !next.focus );\r
109\r
110 // If available, just focus it, otherwise focus the\r
111 // first one.\r
112 if ( next )\r
113 next.focus();\r
114 else\r
115 // Send a TAB.\r
116 itemKeystroke( item, 9 );\r
117\r
118 return false;\r
119 case 40: // DOWN-ARROW\r
120 if ( item.button && item.button.hasArrow ) {\r
c63493c8
IB
121 item.execute();\r
122 } else {\r
123 // Send left arrow key.\r
124 itemKeystroke( item, keystroke == 40 ? rightKeyCode : leftKeyCode );\r
125 }\r
126 return false;\r
127 case leftKeyCode:\r
128 case 38: // UP-ARROW\r
129 next = item;\r
130 do {\r
131 // Look for the previous item in the toolbar.\r
132 next = next.previous;\r
133\r
134 // If it's the first item, cycle to the last one.\r
135 if ( !next && toolbarGroupCycling ) next = item.toolbar.items[ item.toolbar.items.length - 1 ];\r
136 }\r
137 while ( next && !next.focus );\r
138\r
139 // If available, just focus it, otherwise focus the\r
140 // last one.\r
141 if ( next )\r
142 next.focus();\r
143 else {\r
144 endFlag = 1;\r
145 // Send a SHIFT + TAB.\r
146 itemKeystroke( item, CKEDITOR.SHIFT + 9 );\r
147 endFlag = 0;\r
148 }\r
149\r
150 return false;\r
151\r
152 case 27: // ESC\r
153 editor.focus();\r
154 return false;\r
155\r
156 case 13: // ENTER\r
157 case 32: // SPACE\r
158 item.execute();\r
159 return false;\r
160 }\r
161 return true;\r
162 };\r
163\r
164 editor.on( 'uiSpace', function( event ) {\r
165 if ( event.data.space != editor.config.toolbarLocation )\r
166 return;\r
167\r
168 // Create toolbar only once.\r
169 event.removeListener();\r
170\r
171 editor.toolbox = new toolbox();\r
172\r
173 var labelId = CKEDITOR.tools.getNextId();\r
174\r
175 var output = [\r
176 '<span id="', labelId, '" class="cke_voice_label">', editor.lang.toolbar.toolbars, '</span>',\r
177 '<span id="' + editor.ui.spaceId( 'toolbox' ) + '" class="cke_toolbox" role="group" aria-labelledby="', labelId, '" onmousedown="return false;">'\r
178 ];\r
179\r
180 var expanded = editor.config.toolbarStartupExpanded !== false,\r
181 groupStarted, pendingSeparator;\r
182\r
183 // If the toolbar collapser will be available, we'll have\r
184 // an additional container for all toolbars.\r
185 if ( editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE )\r
186 output.push( '<span class="cke_toolbox_main"' + ( expanded ? '>' : ' style="display:none">' ) );\r
187\r
188 var toolbars = editor.toolbox.toolbars,\r
189 toolbar = getToolbarConfig( editor ),\r
190 toolbarLength = toolbar.length;\r
191\r
192 for ( var r = 0; r < toolbarLength; r++ ) {\r
193 var toolbarId,\r
194 toolbarObj = 0,\r
195 toolbarName,\r
196 row = toolbar[ r ],\r
197 lastToolbarInRow = row !== '/' && ( toolbar[ r + 1 ] === '/' || r == toolbarLength - 1 ),\r
198 items;\r
199\r
200 // It's better to check if the row object is really\r
201 // available because it's a common mistake to leave\r
202 // an extra comma in the toolbar definition\r
203 // settings, which leads on the editor not loading\r
1794320d 204 // at all in IE. (http://dev.ckeditor.com/ticket/3983)\r
c63493c8
IB
205 if ( !row )\r
206 continue;\r
207\r
208 if ( groupStarted ) {\r
209 output.push( '</span>' );\r
210 groupStarted = 0;\r
211 pendingSeparator = 0;\r
212 }\r
213\r
214 if ( row === '/' ) {\r
215 output.push( '<span class="cke_toolbar_break"></span>' );\r
216 continue;\r
217 }\r
218\r
219 items = row.items || row;\r
220\r
221 // Create all items defined for this toolbar.\r
222 for ( var i = 0; i < items.length; i++ ) {\r
223 var item = items[ i ],\r
224 canGroup;\r
225\r
226 if ( item ) {\r
227 if ( item.type == CKEDITOR.UI_SEPARATOR ) {\r
228 // Do not add the separator immediately. Just save\r
229 // it be included if we already have something in\r
230 // the toolbar and if a new item is to be added (later).\r
231 pendingSeparator = groupStarted && item;\r
232 continue;\r
233 }\r
234\r
235 canGroup = item.canGroup !== false;\r
236\r
237 // Initialize the toolbar first, if needed.\r
238 if ( !toolbarObj ) {\r
239 // Create the basic toolbar object.\r
240 toolbarId = CKEDITOR.tools.getNextId();\r
241 toolbarObj = { id: toolbarId, items: [] };\r
242 toolbarName = row.name && ( editor.lang.toolbar.toolbarGroups[ row.name ] || row.name );\r
243\r
244 // Output the toolbar opener.\r
245 output.push( '<span id="', toolbarId, '" class="cke_toolbar' + ( lastToolbarInRow ? ' cke_toolbar_last"' : '"' ),\r
246 ( toolbarName ? ' aria-labelledby="' + toolbarId + '_label"' : '' ), ' role="toolbar">' );\r
247\r
248 // If a toolbar name is available, send the voice label.\r
249 toolbarName && output.push( '<span id="', toolbarId, '_label" class="cke_voice_label">', toolbarName, '</span>' );\r
250\r
251 output.push( '<span class="cke_toolbar_start"></span>' );\r
252\r
253 // Add the toolbar to the "editor.toolbox.toolbars"\r
254 // array.\r
255 var index = toolbars.push( toolbarObj ) - 1;\r
256\r
257 // Create the next/previous reference.\r
258 if ( index > 0 ) {\r
259 toolbarObj.previous = toolbars[ index - 1 ];\r
260 toolbarObj.previous.next = toolbarObj;\r
261 }\r
262 }\r
263\r
264 if ( canGroup ) {\r
265 if ( !groupStarted ) {\r
266 output.push( '<span class="cke_toolgroup" role="presentation">' );\r
267 groupStarted = 1;\r
268 }\r
269 } else if ( groupStarted ) {\r
270 output.push( '</span>' );\r
271 groupStarted = 0;\r
272 }\r
273\r
274 function addItem( item ) { // jshint ignore:line\r
275 var itemObj = item.render( editor, output );\r
276 index = toolbarObj.items.push( itemObj ) - 1;\r
277\r
278 if ( index > 0 ) {\r
279 itemObj.previous = toolbarObj.items[ index - 1 ];\r
280 itemObj.previous.next = itemObj;\r
281 }\r
282\r
283 itemObj.toolbar = toolbarObj;\r
284 itemObj.onkey = itemKeystroke;\r
285\r
1794320d 286 // Fix for http://dev.ckeditor.com/ticket/3052:\r
c63493c8
IB
287 // Prevent JAWS from focusing the toolbar after document load.\r
288 itemObj.onfocus = function() {\r
289 if ( !editor.toolbox.focusCommandExecuted )\r
290 editor.focus();\r
291 };\r
292 }\r
293\r
294 if ( pendingSeparator ) {\r
295 addItem( pendingSeparator );\r
296 pendingSeparator = 0;\r
297 }\r
298\r
299 addItem( item );\r
300 }\r
301 }\r
302\r
303 if ( groupStarted ) {\r
304 output.push( '</span>' );\r
305 groupStarted = 0;\r
306 pendingSeparator = 0;\r
307 }\r
308\r
309 if ( toolbarObj )\r
310 output.push( '<span class="cke_toolbar_end"></span></span>' );\r
311 }\r
312\r
313 if ( editor.config.toolbarCanCollapse )\r
314 output.push( '</span>' );\r
315\r
316 // Not toolbar collapser for inline mode.\r
317 if ( editor.config.toolbarCanCollapse && editor.elementMode != CKEDITOR.ELEMENT_MODE_INLINE ) {\r
318 var collapserFn = CKEDITOR.tools.addFunction( function() {\r
319 editor.execCommand( 'toolbarCollapse' );\r
320 } );\r
321\r
322 editor.on( 'destroy', function() {\r
323 CKEDITOR.tools.removeFunction( collapserFn );\r
324 } );\r
325\r
326 editor.addCommand( 'toolbarCollapse', {\r
327 readOnly: 1,\r
328 exec: function( editor ) {\r
329 var collapser = editor.ui.space( 'toolbar_collapser' ),\r
330 toolbox = collapser.getPrevious(),\r
331 contents = editor.ui.space( 'contents' ),\r
332 toolboxContainer = toolbox.getParent(),\r
333 contentHeight = parseInt( contents.$.style.height, 10 ),\r
334 previousHeight = toolboxContainer.$.offsetHeight,\r
335 minClass = 'cke_toolbox_collapser_min',\r
336 collapsed = collapser.hasClass( minClass );\r
337\r
338 if ( !collapsed ) {\r
339 toolbox.hide();\r
340 collapser.addClass( minClass );\r
341 collapser.setAttribute( 'title', editor.lang.toolbar.toolbarExpand );\r
342 } else {\r
343 toolbox.show();\r
344 collapser.removeClass( minClass );\r
345 collapser.setAttribute( 'title', editor.lang.toolbar.toolbarCollapse );\r
346 }\r
347\r
348 // Update collapser symbol.\r
349 collapser.getFirst().setText( collapsed ? '\u25B2' : // BLACK UP-POINTING TRIANGLE\r
350 '\u25C0' ); // BLACK LEFT-POINTING TRIANGLE\r
351\r
352 var dy = toolboxContainer.$.offsetHeight - previousHeight;\r
353 contents.setStyle( 'height', ( contentHeight - dy ) + 'px' );\r
354\r
355 editor.fire( 'resize', {\r
356 outerHeight: editor.container.$.offsetHeight,\r
357 contentsHeight: contents.$.offsetHeight,\r
358 outerWidth: editor.container.$.offsetWidth\r
359 } );\r
360 },\r
361\r
362 modes: { wysiwyg: 1, source: 1 }\r
363 } );\r
364\r
365 editor.setKeystroke( CKEDITOR.ALT + ( CKEDITOR.env.ie || CKEDITOR.env.webkit ? 189 : 109 ) /*-*/, 'toolbarCollapse' );\r
366\r
367 output.push( '<a title="' + ( expanded ? editor.lang.toolbar.toolbarCollapse : editor.lang.toolbar.toolbarExpand ) +\r
368 '" id="' + editor.ui.spaceId( 'toolbar_collapser' ) +\r
369 '" tabIndex="-1" class="cke_toolbox_collapser' );\r
370\r
371 if ( !expanded )\r
372 output.push( ' cke_toolbox_collapser_min' );\r
373\r
374 output.push( '" onclick="CKEDITOR.tools.callFunction(' + collapserFn + ')">', '<span class="cke_arrow">&#9650;</span>', // BLACK UP-POINTING TRIANGLE\r
375 '</a>' );\r
376 }\r
377\r
378 output.push( '</span>' );\r
379 event.data.html += output.join( '' );\r
380 } );\r
381\r
382 editor.on( 'destroy', function() {\r
383 if ( this.toolbox ) {\r
384 var toolbars,\r
385 index = 0,\r
386 i, items, instance;\r
387 toolbars = this.toolbox.toolbars;\r
388 for ( ; index < toolbars.length; index++ ) {\r
389 items = toolbars[ index ].items;\r
390 for ( i = 0; i < items.length; i++ ) {\r
391 instance = items[ i ];\r
392 if ( instance.clickFn )\r
393 CKEDITOR.tools.removeFunction( instance.clickFn );\r
394 if ( instance.keyDownFn )\r
395 CKEDITOR.tools.removeFunction( instance.keyDownFn );\r
396 }\r
397 }\r
398 }\r
399 } );\r
400\r
401 // Manage editor focus when navigating the toolbar.\r
402 editor.on( 'uiReady', function() {\r
403 var toolbox = editor.ui.space( 'toolbox' );\r
404 toolbox && editor.focusManager.add( toolbox, 1 );\r
405 } );\r
406\r
407 editor.addCommand( 'toolbarFocus', commands.toolbarFocus );\r
408 editor.setKeystroke( CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus' );\r
409\r
410 editor.ui.add( '-', CKEDITOR.UI_SEPARATOR, {} );\r
411 editor.ui.addHandler( CKEDITOR.UI_SEPARATOR, {\r
412 create: function() {\r
413 return {\r
414 render: function( editor, output ) {\r
415 output.push( '<span class="cke_toolbar_separator" role="separator"></span>' );\r
416 return {};\r
417 }\r
418 };\r
419 }\r
420 } );\r
421 }\r
422 } );\r
423\r
424 function getToolbarConfig( editor ) {\r
425 var removeButtons = editor.config.removeButtons;\r
426\r
427 removeButtons = removeButtons && removeButtons.split( ',' );\r
428\r
429 function buildToolbarConfig() {\r
430\r
431 // Object containing all toolbar groups used by ui items.\r
432 var lookup = getItemDefinedGroups();\r
433\r
434 // Take the base for the new toolbar, which is basically a toolbar\r
435 // definition without items.\r
436 var toolbar = CKEDITOR.tools.clone( editor.config.toolbarGroups ) || getPrivateToolbarGroups( editor );\r
437\r
438 // Fill the toolbar groups with the available ui items.\r
439 for ( var i = 0; i < toolbar.length; i++ ) {\r
440 var toolbarGroup = toolbar[ i ];\r
441\r
442 // Skip toolbar break.\r
443 if ( toolbarGroup == '/' )\r
444 continue;\r
445 // Handle simply group name item.\r
446 else if ( typeof toolbarGroup == 'string' )\r
447 toolbarGroup = toolbar[ i ] = { name: toolbarGroup };\r
448\r
449 var items, subGroups = toolbarGroup.groups;\r
450\r
451 // Look for items that match sub groups.\r
452 if ( subGroups ) {\r
453 for ( var j = 0, sub; j < subGroups.length; j++ ) {\r
454 sub = subGroups[ j ];\r
455\r
456 // If any ui item is registered for this subgroup.\r
457 items = lookup[ sub ];\r
458 items && fillGroup( toolbarGroup, items );\r
459 }\r
460 }\r
461\r
462 // Add the main group items as well.\r
463 items = lookup[ toolbarGroup.name ];\r
464 items && fillGroup( toolbarGroup, items );\r
465 }\r
466\r
467 return toolbar;\r
468 }\r
469\r
470 // Returns an object containing all toolbar groups used by ui items.\r
471 function getItemDefinedGroups() {\r
472 var groups = {},\r
473 itemName, item, itemToolbar, group, order;\r
474\r
475 for ( itemName in editor.ui.items ) {\r
476 item = editor.ui.items[ itemName ];\r
477 itemToolbar = item.toolbar || 'others';\r
478 if ( itemToolbar ) {\r
479 // Break the toolbar property into its parts: "group_name[,order]".\r
480 itemToolbar = itemToolbar.split( ',' );\r
481 group = itemToolbar[ 0 ];\r
482 order = parseInt( itemToolbar[ 1 ] || -1, 10 );\r
483\r
484 // Initialize the group, if necessary.\r
485 groups[ group ] || ( groups[ group ] = [] );\r
486\r
487 // Push the data used to build the toolbar later.\r
488 groups[ group ].push( { name: itemName, order: order } );\r
489 }\r
490 }\r
491\r
492 // Put the items in the right order.\r
493 for ( group in groups ) {\r
494 groups[ group ] = groups[ group ].sort( function( a, b ) {\r
495 return a.order == b.order ? 0 :\r
496 b.order < 0 ? -1 :\r
497 a.order < 0 ? 1 :\r
498 a.order < b.order ? -1 :\r
499 1;\r
500 } );\r
501 }\r
502\r
503 return groups;\r
504 }\r
505\r
506 function fillGroup( toolbarGroup, uiItems ) {\r
507 if ( uiItems.length ) {\r
508 if ( toolbarGroup.items )\r
509 toolbarGroup.items.push( editor.ui.create( '-' ) );\r
510 else\r
511 toolbarGroup.items = [];\r
512\r
513 var item, name;\r
514 while ( ( item = uiItems.shift() ) ) {\r
515 name = typeof item == 'string' ? item : item.name;\r
516\r
517 // Ignore items that are configured to be removed.\r
518 if ( !removeButtons || CKEDITOR.tools.indexOf( removeButtons, name ) == -1 ) {\r
519 item = editor.ui.create( name );\r
520\r
521 if ( !item )\r
522 continue;\r
523\r
524 if ( !editor.addFeature( item ) )\r
525 continue;\r
526\r
527 toolbarGroup.items.push( item );\r
528 }\r
529 }\r
530 }\r
531 }\r
532\r
533 function populateToolbarConfig( config ) {\r
534 var toolbar = [],\r
535 i, group, newGroup;\r
536\r
537 for ( i = 0; i < config.length; ++i ) {\r
538 group = config[ i ];\r
539 newGroup = {};\r
540\r
541 if ( group == '/' )\r
542 toolbar.push( group );\r
543 else if ( CKEDITOR.tools.isArray( group ) ) {\r
544 fillGroup( newGroup, CKEDITOR.tools.clone( group ) );\r
545 toolbar.push( newGroup );\r
546 }\r
547 else if ( group.items ) {\r
548 fillGroup( newGroup, CKEDITOR.tools.clone( group.items ) );\r
549 newGroup.name = group.name;\r
550 toolbar.push( newGroup );\r
551 }\r
552 }\r
553\r
554 return toolbar;\r
555 }\r
556\r
557 var toolbar = editor.config.toolbar;\r
558\r
559 // If it is a string, return the relative "toolbar_name" config.\r
560 if ( typeof toolbar == 'string' )\r
561 toolbar = editor.config[ 'toolbar_' + toolbar ];\r
562\r
563 return ( editor.toolbar = toolbar ? populateToolbarConfig( toolbar ) : buildToolbarConfig() );\r
564 }\r
565\r
566 /**\r
567 * Adds a toolbar group. See {@link CKEDITOR.config#toolbarGroups} for more details.\r
568 *\r
569 * **Note:** This method will not modify toolbar groups set explicitly by\r
570 * {@link CKEDITOR.config#toolbarGroups}. It will only extend the default setting.\r
571 *\r
572 * @param {String} name Toolbar group name.\r
573 * @param {Number/String} previous The name of the toolbar group after which this one\r
574 * should be added or `0` if this group should be the first one.\r
575 * @param {String} [subgroupOf] The name of the parent group.\r
576 * @member CKEDITOR.ui\r
577 */\r
578 CKEDITOR.ui.prototype.addToolbarGroup = function( name, previous, subgroupOf ) {\r
579 // The toolbarGroups from the privates is the one we gonna use for automatic toolbar creation.\r
580 var toolbarGroups = getPrivateToolbarGroups( this.editor ),\r
581 atStart = previous === 0,\r
582 newGroup = { name: name };\r
583\r
584 if ( subgroupOf ) {\r
585 // Transform the subgroupOf name in the real subgroup object.\r
586 subgroupOf = CKEDITOR.tools.search( toolbarGroups, function( group ) {\r
587 return group.name == subgroupOf;\r
588 } );\r
589\r
590 if ( subgroupOf ) {\r
591 !subgroupOf.groups && ( subgroupOf.groups = [] ) ;\r
592\r
593 if ( previous ) {\r
594 // Search the "previous" item and add the new one after it.\r
595 previous = CKEDITOR.tools.indexOf( subgroupOf.groups, previous );\r
596 if ( previous >= 0 ) {\r
597 subgroupOf.groups.splice( previous + 1, 0, name );\r
598 return;\r
599 }\r
600 }\r
601\r
602 // If no previous found.\r
603\r
604 if ( atStart )\r
605 subgroupOf.groups.splice( 0, 0, name );\r
606 else\r
607 subgroupOf.groups.push( name );\r
608 return;\r
609 } else {\r
610 // Ignore "previous" if subgroupOf has not been found.\r
611 previous = null;\r
612 }\r
613 }\r
614\r
615 if ( previous ) {\r
616 // Transform the "previous" name into its index.\r
617 previous = CKEDITOR.tools.indexOf( toolbarGroups, function( group ) {\r
618 return group.name == previous;\r
619 } );\r
620 }\r
621\r
622 if ( atStart )\r
623 toolbarGroups.splice( 0, 0, name );\r
624 else if ( typeof previous == 'number' )\r
625 toolbarGroups.splice( previous + 1, 0, newGroup );\r
626 else\r
627 toolbarGroups.push( name );\r
628 };\r
629\r
630 function getPrivateToolbarGroups( editor ) {\r
631 return editor._.toolbarGroups || ( editor._.toolbarGroups = [\r
632 { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },\r
633 { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },\r
634 { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },\r
635 { name: 'forms' },\r
636 '/',\r
637 { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },\r
638 { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },\r
639 { name: 'links' },\r
640 { name: 'insert' },\r
641 '/',\r
642 { name: 'styles' },\r
643 { name: 'colors' },\r
644 { name: 'tools' },\r
645 { name: 'others' },\r
646 { name: 'about' }\r
647 ] );\r
648 }\r
649} )();\r
650\r
651/**\r
652 * Separator UI element.\r
653 *\r
654 * @readonly\r
655 * @property {String} [='separator']\r
656 * @member CKEDITOR\r
657 */\r
658CKEDITOR.UI_SEPARATOR = 'separator';\r
659\r
660/**\r
661 * The part of the user interface where the toolbar will be rendered. For the default\r
662 * editor implementation, the recommended options are `'top'` and `'bottom'`.\r
663 *\r
664 * Please note that this option is only applicable to [classic](#!/guide/dev_framed)\r
665 * (`iframe`-based) editor. In case of [inline](#!/guide/dev_inline) editor the toolbar\r
666 * position is set dynamically depending on the position of the editable element on the screen.\r
667 *\r
668 * Read more in the [documentation](#!/guide/dev_toolbarlocation)\r
669 * and see the [SDK sample](http://sdk.ckeditor.com/samples/toolbarlocation.html).\r
670 *\r
671 * config.toolbarLocation = 'bottom';\r
672 *\r
673 * @cfg\r
674 * @member CKEDITOR.config\r
675 */\r
676CKEDITOR.config.toolbarLocation = 'top';\r
677\r
678/**\r
679 * The toolbox (alias toolbar) definition. It is a toolbar name or an array of\r
680 * toolbars (strips), each one being also an array, containing a list of UI items.\r
681 *\r
682 * If set to `null`, the toolbar will be generated automatically using all available buttons\r
683 * and {@link #toolbarGroups} as a toolbar groups layout.\r
684 *\r
685 * In CKEditor 4.5+ you can generate your toolbar customization code by using the [visual\r
686 * toolbar configurator](http://docs.ckeditor.com/#!/guide/dev_toolbar).\r
687 *\r
688 * // Defines a toolbar with only one strip containing the "Source" button, a\r
689 * // separator, and the "Bold" and "Italic" buttons.\r
690 * config.toolbar = [\r
691 * [ 'Source', '-', 'Bold', 'Italic' ]\r
692 * ];\r
693 *\r
694 * // Similar to the example above, defines a "Basic" toolbar with only one strip containing three buttons.\r
695 * // Note that this setting is composed by "toolbar_" added to the toolbar name, which in this case is called "Basic".\r
696 * // This second part of the setting name can be anything. You must use this name in the CKEDITOR.config.toolbar setting\r
697 * // in order to instruct the editor which `toolbar_(name)` setting should be used.\r
698 * config.toolbar_Basic = [\r
699 * [ 'Source', '-', 'Bold', 'Italic' ]\r
700 * ];\r
701 * // Load toolbar_Name where Name = Basic.\r
702 * config.toolbar = 'Basic';\r
703 *\r
704 * @cfg {Array/String} [toolbar=null]\r
705 * @member CKEDITOR.config\r
706 */\r
707\r
708/**\r
709 * The toolbar groups definition.\r
710 *\r
711 * If the toolbar layout is not explicitly defined by the {@link #toolbar} setting, then\r
712 * this setting is used to group all defined buttons (see {@link CKEDITOR.ui#addButton}).\r
713 * Buttons are associated with toolbar groups by the `toolbar` property in their definition objects.\r
714 *\r
715 * New groups may be dynamically added during the editor and plugin initialization by\r
716 * {@link CKEDITOR.ui#addToolbarGroup}. This is only possible if the default setting was used.\r
717 *\r
718 * // Default setting.\r
719 * config.toolbarGroups = [\r
720 * { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },\r
721 * { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },\r
722 * { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },\r
723 * { name: 'forms' },\r
724 * '/',\r
725 * { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },\r
726 * { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },\r
727 * { name: 'links' },\r
728 * { name: 'insert' },\r
729 * '/',\r
730 * { name: 'styles' },\r
731 * { name: 'colors' },\r
732 * { name: 'tools' },\r
733 * { name: 'others' },\r
734 * { name: 'about' }\r
735 * ];\r
736 *\r
737 * @cfg {Array} [toolbarGroups=see example]\r
738 * @member CKEDITOR.config\r
739 */\r
740\r
741/**\r
742 * Whether the toolbar can be collapsed by the user. If disabled, the Collapse Toolbar\r
743 * button will not be displayed.\r
744 *\r
745 * config.toolbarCanCollapse = true;\r
746 *\r
747 * @cfg {Boolean} [toolbarCanCollapse=false]\r
748 * @member CKEDITOR.config\r
749 */\r
750\r
751/**\r
752 * Whether the toolbar must start expanded when the editor is loaded.\r
753 *\r
754 * Setting this option to `false` will affect the toolbar only when\r
755 * {@link #toolbarCanCollapse} is set to `true`:\r
756 *\r
757 * config.toolbarCanCollapse = true;\r
758 * config.toolbarStartupExpanded = false;\r
759 *\r
760 * @cfg {Boolean} [toolbarStartupExpanded=true]\r
761 * @member CKEDITOR.config\r
762 */\r
763\r
764/**\r
765 * When enabled, causes the *Arrow* keys navigation to cycle within the current\r
766 * toolbar group. Otherwise the *Arrow* keys will move through all items available in\r
767 * the toolbar. The *Tab* key will still be used to quickly jump among the\r
768 * toolbar groups.\r
769 *\r
770 * config.toolbarGroupCycling = false;\r
771 *\r
772 * @since 3.6\r
773 * @cfg {Boolean} [toolbarGroupCycling=true]\r
774 * @member CKEDITOR.config\r
775 */\r
776\r
777/**\r
778 * List of toolbar button names that must not be rendered. This will also work\r
779 * for non-button toolbar items, like the Font drop-down list.\r
780 *\r
781 * config.removeButtons = 'Underline,JustifyCenter';\r
782 *\r
783 * This configuration option should not be overused. The recommended way is to use the\r
784 * {@link CKEDITOR.config#removePlugins} setting to remove features from the editor\r
785 * or even better, [create a custom editor build](http://ckeditor.com/builder) with\r
786 * just the features that you will use.\r
787 * In some cases though, a single plugin may define a set of toolbar buttons and\r
788 * `removeButtons` may be useful when just a few of them are to be removed.\r
789 *\r
790 * @cfg {String} [removeButtons]\r
791 * @member CKEDITOR.config\r
792 */\r
793\r
794/**\r
795 * The toolbar definition used by the editor. It is created from the\r
796 * {@link CKEDITOR.config#toolbar} option if it is set or automatically\r
797 * based on {@link CKEDITOR.config#toolbarGroups}.\r
798 *\r
799 * @readonly\r
800 * @property {Object} toolbar\r
801 * @member CKEDITOR.editor\r
802 */\r