deletecontents.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. import LivePosition from '../liveposition.js';
  7. import Position from '../position.js';
  8. import compareArrays from '../../../utils/comparearrays.js';
  9. /**
  10. * Delete contents of the selection and merge siblings. The resulting selection is always collapsed.
  11. *
  12. * @method engine.model.composer.deleteContents
  13. * @param {engine.model.Batch} batch Batch to which the deltas will be added.
  14. * @param {engine.model.Selection} selection Selection of which the content should be deleted.
  15. * @param {Object} [options]
  16. * @param {Boolean} [options.merge=false] Merge elements after removing the contents of the selection.
  17. * For example, `<h>x[x</h><p>y]y</p>` will become: `<h>x^y</h>` with the option enabled
  18. * and: `<h>x^</h><p>y</p>` without it.
  19. */
  20. export default function deleteContents( batch, selection, options = {} ) {
  21. if ( selection.isCollapsed ) {
  22. return;
  23. }
  24. const selRange = selection.getFirstRange();
  25. const startPos = selRange.start;
  26. const endPos = LivePosition.createFromPosition( selRange.end );
  27. // 1. Remove the contents if there are any.
  28. if ( !selRange.isEmpty ) {
  29. batch.remove( selRange );
  30. }
  31. // 2. Merge elements in the right branch to the elements in the left branch.
  32. // The only reasonable (in terms of data and selection correctness) case in which we need to do that is:
  33. //
  34. // <heading type=1>Fo[</heading><paragraph>]ar</paragraph> => <heading type=1>Fo^ar</heading>
  35. //
  36. // However, the algorithm supports also merging deeper structures (up to the depth of the shallower branch),
  37. // as it's hard to imagine what should actually be the default behavior. Usually, specific features will
  38. // want to override that behavior anyway.
  39. if ( options.merge ) {
  40. const endPath = endPos.path;
  41. const mergeEnd = Math.min( startPos.path.length - 1, endPath.length - 1 );
  42. let mergeDepth = compareArrays( startPos.path, endPath );
  43. if ( typeof mergeDepth == 'number' ) {
  44. for ( ; mergeDepth < mergeEnd; mergeDepth++ ) {
  45. const mergePath = startPos.path.slice( 0, mergeDepth );
  46. mergePath.push( startPos.path[ mergeDepth ] + 1 );
  47. batch.merge( new Position( endPos.root, mergePath ) );
  48. }
  49. }
  50. }
  51. selection.collapse( startPos );
  52. endPos.detach();
  53. }