8
0

indent-block.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /* globals console, window, document */
  6. import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
  7. import MultiCommand from '@ckeditor/ckeditor5-core/src/multicommand';
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
  10. import Command from '@ckeditor/ckeditor5-core/src/command';
  11. import first from '@ckeditor/ckeditor5-utils/src/first';
  12. import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset';
  13. class IndentBlockCommand extends Command {
  14. /**
  15. * @inheritDoc
  16. */
  17. refresh() {
  18. this.isEnabled = this._checkEnabled();
  19. }
  20. /**
  21. * Indents or outdents (depends on the {@link #constructor}'s `indentDirection` parameter) selected list items.
  22. *
  23. * @fires execute
  24. */
  25. execute() {
  26. const model = this.editor.model;
  27. const doc = model.document;
  28. const itemsToChange = Array.from( doc.selection.getSelectedBlocks() );
  29. model.change( () => {
  30. for ( const item of itemsToChange ) {
  31. console.log( 'indent block', item );
  32. }
  33. } );
  34. }
  35. /**
  36. * Checks whether the command can be enabled in the current context.
  37. *
  38. * @private
  39. * @returns {Boolean} Whether the command should be enabled.
  40. */
  41. _checkEnabled() {
  42. // Check whether any of position's ancestor is a list item.
  43. const block = first( this.editor.model.document.selection.getSelectedBlocks() );
  44. // If selection is not in a list item, the command is disabled.
  45. if ( !block || !this.editor.model.schema.checkAttribute( block, 'indent' ) ) {
  46. return false;
  47. }
  48. return true;
  49. }
  50. }
  51. class IndentOutdent extends Plugin {
  52. init() {
  53. const editor = this.editor;
  54. const t = editor.t;
  55. this._createButton( 'indent', t( 'Indent' ) );
  56. // this._createButton( 'outdent', t( 'Outdent' ) );
  57. this._createButton( 'indentList', t( 'Indent List' ) );
  58. // this._createButton( 'outdentList', t( 'Outdent List' ) );
  59. this._createButton( 'indentBlock', t( 'Indent Block' ) );
  60. // this._createButton( 'outdentBlock', t( 'Outdent Block' ) );
  61. }
  62. _createButton( commandName, label ) {
  63. const editor = this.editor;
  64. editor.ui.componentFactory.add( commandName, locale => {
  65. const command = editor.commands.get( commandName );
  66. const view = new ButtonView( locale );
  67. view.set( {
  68. label,
  69. withText: true,
  70. tooltip: true
  71. } );
  72. view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
  73. // Execute command.
  74. this.listenTo( view, 'execute', () => editor.execute( commandName ) );
  75. return view;
  76. } );
  77. }
  78. afterInit() {
  79. const editor = this.editor;
  80. editor.commands.add( 'indentBlock', new IndentBlockCommand( editor ) );
  81. const indentCommand = new MultiCommand( editor );
  82. indentCommand.registerChildCommand( editor.commands.get( 'indentList' ) );
  83. indentCommand.registerChildCommand( editor.commands.get( 'indentBlock' ) );
  84. editor.commands.add( 'indent', indentCommand );
  85. // TODO nicer API?
  86. // editor.commands.add( 'indentList', new Command(), 'indent' );
  87. // editor.commands.addMulti( 'indentList', new Command(), 'indent' );
  88. // editor.commands.addMulti( 'indentList', 'indent' );
  89. const outdentCommand = new MultiCommand( editor );
  90. outdentCommand.registerChildCommand( editor.commands.get( 'outdentList' ) );
  91. editor.commands.add( 'outdent', outdentCommand );
  92. }
  93. }
  94. class IndentBlock extends Plugin {
  95. init() {
  96. const schema = this.editor.model.schema;
  97. const conversion = this.editor.conversion;
  98. schema.extend( 'paragraph', { allowAttributes: 'indent' } );
  99. schema.extend( 'heading1', { allowAttributes: 'indent' } );
  100. conversion.for( 'upcast' ).attributeToAttribute( {
  101. view: {
  102. styles: {
  103. 'margin-left': /[\s\S]+/
  104. }
  105. },
  106. model: {
  107. key: 'indent',
  108. value: viewElement => {
  109. return viewElement.getStyle( 'margin-left' );
  110. }
  111. }
  112. } );
  113. conversion.for( 'downcast' ).attributeToAttribute( {
  114. model: 'indent',
  115. view: modelAttributeValue => {
  116. return {
  117. key: 'style',
  118. value: {
  119. 'margin-left': modelAttributeValue
  120. }
  121. };
  122. }
  123. } );
  124. }
  125. }
  126. ClassicEditor
  127. .create( document.querySelector( '#editor' ), {
  128. plugins: [ ArticlePluginSet, IndentOutdent, IndentBlock ],
  129. toolbar: [
  130. 'heading',
  131. // '|',
  132. // 'bold',
  133. // 'italic',
  134. // 'link',
  135. '|',
  136. 'indent',
  137. 'outdent',
  138. '|',
  139. 'indentList',
  140. 'outdentList',
  141. '|',
  142. 'indentBlock',
  143. 'outdentBlock',
  144. '|',
  145. 'bulletedList',
  146. 'numberedList',
  147. '|',
  148. // 'blockQuote',
  149. // 'insertTable',
  150. // 'mediaEmbed',
  151. 'undo',
  152. 'redo'
  153. ],
  154. image: {
  155. toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]
  156. },
  157. table: {
  158. contentToolbar: [
  159. 'tableColumn',
  160. 'tableRow',
  161. 'mergeTableCells'
  162. ]
  163. }
  164. } )
  165. .then( editor => {
  166. window.editor = editor;
  167. } )
  168. .catch( err => {
  169. console.error( err.stack );
  170. } );