8
0

keystrokehandler.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import EmitterMixin from './utils/emittermixin.js';
  6. import { getCode, parseKeystroke } from './utils/keyboard.js';
  7. /**
  8. * Keystroke handler. Its instance is available in {@link ckeditor5.Editor#keystrokes} so features
  9. * can register their keystrokes.
  10. *
  11. * E.g. an undo feature would do this:
  12. *
  13. * editor.keystrokes.set( 'ctrl + Z', 'undo' );
  14. * editor.keystrokes.set( 'ctrl + shift + Z', 'redo' );
  15. * editor.keystrokes.set( 'ctrl + Y', 'redo' );
  16. *
  17. * @memberOf ckeditor5
  18. */
  19. export default class KeystrokeHandler {
  20. /**
  21. * Creates an instance of the keystroke handler.
  22. *
  23. * @param {engine.treeView.TreeView} editingView
  24. */
  25. constructor( editor ) {
  26. /**
  27. * The editor instance.
  28. *
  29. * @readonly
  30. * @member {ckeditor5.Editor} ckeditor5.KeystrokeHandler#editor
  31. */
  32. this.editor = editor;
  33. /**
  34. * Listener used to listen to events for easier keystroke handler destruction.
  35. *
  36. * @private
  37. * @member {utils.Emitter} ckeditor5.KeystrokeHandler#_listener
  38. */
  39. this._listener = Object.create( EmitterMixin );
  40. /**
  41. * Map of the defined keystrokes. Keystroke codes are the keys.
  42. *
  43. * @private
  44. * @member {Map} ckeditor5.KeystrokeHandler#_keystrokes
  45. */
  46. this._keystrokes = new Map();
  47. this._listener.listenTo( editor.editing.view, 'keydown', ( evt, data ) => {
  48. const handled = this.press( data );
  49. if ( handled ) {
  50. data.preventDefault();
  51. }
  52. } );
  53. }
  54. /**
  55. * Registers a handler for the specified keystroke.
  56. *
  57. * The handler can be specified as a command name or a callback.
  58. *
  59. * @param {String|Array.<String|Number>} keystroke Keystroke defined in a format accepted by
  60. * the {@link utils.keyboard.parseKeystroke} function.
  61. * @param {String|Function} callback If a string is passed, then the keystroke will
  62. * {@link ckeditor5.Editor#execute execute a command}.
  63. * If a function, then it will be called with the
  64. * {@link engine.view.observer.keyObserver.KeyEventData key event data} object.
  65. */
  66. set( keystroke, callback ) {
  67. this._keystrokes.set( parseKeystroke( keystroke ), callback );
  68. }
  69. /**
  70. * Triggers a keystroke handler for a specified key combination, if such a keystroke was {@link #set defined}.
  71. *
  72. * @param {engine.view.observer.keyObserver.KeyEventData} keyEventData Key event data.
  73. * @returns {Boolean} Whether the keystroke was handled.
  74. */
  75. press( keyEventData ) {
  76. const keyCode = getCode( keyEventData );
  77. const callback = this._keystrokes.get( keyCode );
  78. if ( !callback ) {
  79. return false;
  80. }
  81. if ( typeof callback == 'string' ) {
  82. this.editor.execute( callback );
  83. } else {
  84. callback( keyEventData );
  85. }
  86. return true;
  87. }
  88. /**
  89. * Destroys the keystroke handler.
  90. */
  91. destroy() {
  92. this._keystrokes = new Map();
  93. this._listener.stopListening();
  94. }
  95. }