8
0

mouseselectionhandler.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module table/tableselection/mouseselectionhandler
  7. */
  8. import mix from '@ckeditor/ckeditor5-utils/src/mix';
  9. import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
  10. import { findAncestor } from '../commands/utils';
  11. import MouseEventsObserver from './mouseeventsobserver';
  12. /**
  13. * A mouse selection handler class for the table selection.
  14. *
  15. * It registers the {@link module:table/tableselection/mouseeventsobserver~MouseEventsObserver} to observe view document mouse events
  16. * and invoke proper {@link module:table/tableselection~TableSelection} actions.
  17. */
  18. export default class MouseSelectionHandler {
  19. /**
  20. * Creates an instance of the `MouseSelectionHandler`.
  21. *
  22. * @param {module:table/tableselection~TableSelection} tableSelection
  23. * @param {module:engine/controller/editingcontroller~EditingController} editing
  24. */
  25. constructor( tableSelection, editing ) {
  26. /**
  27. * The table selection plugin instance.
  28. *
  29. * @private
  30. * @readonly
  31. * @member {module:table/tableselection~TableSelection}
  32. */
  33. this._tableSelection = tableSelection;
  34. /**
  35. * A flag indicating that the mouse selection is "active". A selection is "active" if it was started and not yet finished.
  36. * A selection can be "active", for instance, if a user moves a mouse over a table while holding a mouse button down.
  37. *
  38. * @readonly
  39. * @member {Boolean}
  40. */
  41. this.isSelecting = false;
  42. /**
  43. * Editing mapper.
  44. *
  45. * @private
  46. * @readonly
  47. * @member {module:engine/conversion/mapper~Mapper}
  48. */
  49. this._mapper = editing.mapper;
  50. const view = editing.view;
  51. // Currently the MouseObserver only handles `mouseup` events.
  52. view.addObserver( MouseEventsObserver );
  53. this.listenTo( view.document, 'mousedown', ( event, domEventData ) => this._handleMouseDown( domEventData ) );
  54. this.listenTo( view.document, 'mousemove', ( event, domEventData ) => this._handleMouseMove( domEventData ) );
  55. this.listenTo( view.document, 'mouseup', ( event, domEventData ) => this._handleMouseUp( domEventData ) );
  56. }
  57. /**
  58. * Handles starting a selection when "mousedown" event has table cell as a DOM target.
  59. *
  60. * If there is no table cell in the event target, it will clear the previous selection.
  61. *
  62. * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData
  63. * @private
  64. */
  65. _handleMouseDown( domEventData ) {
  66. const tableCell = this._getModelTableCellFromDomEvent( domEventData );
  67. if ( !tableCell ) {
  68. this._tableSelection.clearSelection();
  69. this._tableSelection.stopSelection();
  70. return;
  71. }
  72. this.isSelecting = true;
  73. this._tableSelection.startSelectingFrom( tableCell );
  74. }
  75. /**
  76. * Handles updating the table selection when the "mousemove" event has a table cell as a DOM target.
  77. *
  78. * Does nothing if there is no table cell in event target or the selection has not been started yet.
  79. *
  80. * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData
  81. * @private
  82. */
  83. _handleMouseMove( domEventData ) {
  84. if ( !isButtonPressed( domEventData ) ) {
  85. this._tableSelection.stopSelection();
  86. return;
  87. }
  88. const tableCell = this._getModelTableCellFromDomEvent( domEventData );
  89. if ( !tableCell ) {
  90. return;
  91. }
  92. this._tableSelection.setSelectingTo( tableCell );
  93. }
  94. /**
  95. * Handles ending (not clearing) the table selection on the "mouseup" event.
  96. *
  97. * Does nothing if the selection has not been started yet.
  98. *
  99. * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData
  100. * @private
  101. */
  102. _handleMouseUp( domEventData ) {
  103. if ( !this.isSelecting ) {
  104. return;
  105. }
  106. const tableCell = this._getModelTableCellFromDomEvent( domEventData );
  107. // Selection can be stopped if table cell is undefined.
  108. this._tableSelection.stopSelection( tableCell );
  109. }
  110. /**
  111. * Finds a model table cell for a given DOM event.
  112. *
  113. * @private
  114. * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData
  115. * @returns {module:engine/model/element~Element|undefined} Returns model table cell or undefined event target is not
  116. * a mapped table cell.
  117. */
  118. _getModelTableCellFromDomEvent( domEventData ) {
  119. const viewTargetElement = domEventData.target;
  120. const modelElement = this._mapper.toModelElement( viewTargetElement );
  121. if ( !modelElement ) {
  122. return;
  123. }
  124. if ( modelElement.is( 'tableCell' ) ) {
  125. return modelElement;
  126. }
  127. return findAncestor( 'tableCell', modelElement );
  128. }
  129. }
  130. mix( MouseSelectionHandler, ObservableMixin );
  131. function isButtonPressed( domEventData ) {
  132. return !!domEventData.domEvent.buttons;
  133. }