8
0

list.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import Feature from '../core/feature.js';
  6. import ListEngine from './listengine.js';
  7. import ButtonView from '../ui/button/buttonview.js';
  8. import { parseKeystroke } from '../utils/keyboard.js';
  9. /**
  10. * The lists feature. It introduces the `numberedList` and `bulletedList` buttons which
  11. * allows to convert paragraphs to/from list items and indent/outdent them.
  12. *
  13. * See also {@link list.ListEngine}.
  14. *
  15. * @memberOf list
  16. * @extends core.Feature
  17. */
  18. export default class List extends Feature {
  19. /**
  20. * @inheritDoc
  21. */
  22. static get requires() {
  23. return [ ListEngine ];
  24. }
  25. /**
  26. * @inheritDoc
  27. */
  28. init() {
  29. // Create two buttons and link them with numberedList and bulletedList commands.
  30. const t = this.editor.t;
  31. this._addButton( 'numberedList', t( 'Numbered List' ) );
  32. this._addButton( 'bulletedList', t( 'Bulleted List' ) );
  33. // Overwrite default enter key behavior.
  34. // If enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it.
  35. this.listenTo( this.editor.editing.view, 'enter', ( evt, data ) => {
  36. const doc = this.editor.document;
  37. const positionParent = doc.selection.getLastPosition().parent;
  38. if ( doc.selection.isCollapsed && positionParent.name == 'listItem' && positionParent.isEmpty ) {
  39. this.editor.execute( 'outdentList' );
  40. data.preventDefault();
  41. evt.stop();
  42. }
  43. } );
  44. // Add tab key support.
  45. // When in list item, pressing tab should indent list item, if possible.
  46. // Pressing shift + tab shout outdent list item.
  47. this.listenTo( this.editor.editing.view, 'keydown', ( evt, data ) => {
  48. let commandName = null;
  49. if ( data.keystroke == parseKeystroke( 'tab' ) ) {
  50. commandName = 'indentList';
  51. } else if ( data.keystroke == parseKeystroke( 'Shift+tab' ) ) {
  52. commandName = 'outdentList';
  53. }
  54. if ( commandName ) {
  55. const command = this.editor.commands.get( commandName );
  56. if ( command.isEnabled ) {
  57. this.editor.execute( commandName );
  58. data.preventDefault();
  59. evt.stop();
  60. }
  61. }
  62. } );
  63. }
  64. /**
  65. * Helper method for initializing a button and linking it with an appropriate command.
  66. *
  67. * @private
  68. * @param {String} commandName Name of the command.
  69. * @param {Object} label Button label.
  70. */
  71. _addButton( commandName, label ) {
  72. const editor = this.editor;
  73. const command = editor.commands.get( commandName );
  74. // Add button to feature components.
  75. editor.ui.featureComponents.add( commandName, ( locale ) => {
  76. const buttonView = new ButtonView( locale );
  77. buttonView.set( {
  78. label: label,
  79. icon: commandName.toLowerCase()
  80. } );
  81. // Bind button model to command.
  82. buttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
  83. // Execute command.
  84. this.listenTo( buttonView, 'execute', () => editor.execute( commandName ) );
  85. return buttonView;
  86. } );
  87. }
  88. }