smartrange.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. CKEDITOR.define( [ 'treemodel/range', 'emittermixin', 'utils' ], ( Range, EmitterMixin, utils ) => {
  7. /**
  8. * SmartRange is a Range in the Tree Model that updates itself as the tree changes. It may be used as a bookmark.
  9. * SmartRange object may fire 'update' event whenever it gets changed by internal mechanisms.
  10. *
  11. * @class treeModel.SmartRange
  12. */
  13. class SmartRange extends Range {
  14. /**
  15. * Creates a smart range.
  16. *
  17. * @see {treeModel.Range}
  18. * @constructor
  19. */
  20. constructor( start, end ) {
  21. super( start, end );
  22. this.listenTo( this.root.document, 'update', transform, this );
  23. }
  24. }
  25. /**
  26. * Updates this position accordingly to the updates applied to the Tree Model. Bases on change events.
  27. *
  28. * @method transform
  29. * @param {String} type Type of changes applied to the Tree Model.
  30. * @param {treeModel.Range} range Range containing the result of applied change.
  31. * @param {treeModel.Position} [position] Additional position parameter provided by some change events.
  32. * @private
  33. */
  34. function transform( type, range, position ) {
  35. /*jshint validthis: true */
  36. let howMany = range.end.offset - range.start.offset;
  37. let newStart, newEnd;
  38. switch ( type ) {
  39. case 'insert':
  40. newStart = this.start.getTransformedByInsertion( range.start, howMany, true );
  41. newEnd = this.end.getTransformedByInsertion( range.start, howMany, false );
  42. break;
  43. case 'move':
  44. case 'remove':
  45. case 'reinsert':
  46. let differenceSet = this.getDifference( Range.createFromPositionAndShift( position, howMany ) );
  47. if ( differenceSet.length > 0 ) {
  48. let diff = differenceSet[ 0 ];
  49. if ( differenceSet.length > 1 ) {
  50. diff.end = differenceSet[ 1 ].end.clone();
  51. }
  52. newStart = diff.start.getTransformedByDeletion( position, howMany ).getTransformedByInsertion( range.start, howMany );
  53. newEnd = diff.end.getTransformedByDeletion( position, howMany ).getTransformedByInsertion( range.start, howMany );
  54. } else {
  55. newStart = this.start._getCombined( position, range.start );
  56. newEnd = this.end._getCombined( position, range.start );
  57. }
  58. break;
  59. }
  60. if ( !newStart.isEqual( this.start ) || !newEnd.isEqual( this.end ) ) {
  61. this.start = newStart;
  62. this.end = newEnd;
  63. this.fire( 'update' );
  64. }
  65. }
  66. utils.extend( SmartRange.prototype, EmitterMixin );
  67. return SmartRange;
  68. } );