plugin.js 25 KB

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