8
0

unwrapdelta.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module engine/model/delta/unwrapdelta
  7. */
  8. import Delta from './delta';
  9. import DeltaFactory from './deltafactory';
  10. import WrapDelta from './wrapdelta';
  11. import { register } from '../batch';
  12. import Position from '../position';
  13. import RemoveOperation from '../operation/removeoperation';
  14. import MoveOperation from '../operation/moveoperation';
  15. import CKEditorError from 'ckeditor5-utils/src/ckeditorerror';
  16. /**
  17. * @classdesc
  18. * To provide specific OT behavior and better collisions solving, {@link module:engine/model/batch~Batch#merge} method
  19. * uses the `UnwrapDelta` class which inherits from the `Delta` class and may overwrite some methods.
  20. */
  21. export default class UnwrapDelta extends Delta {
  22. /**
  23. * Position before unwrapped element or `null` if there are no operations in the delta.
  24. *
  25. * @type {module:engine/model/position~Position|null}
  26. */
  27. get position() {
  28. return this._moveOperation ? this._moveOperation.targetPosition : null;
  29. }
  30. /**
  31. * Operation in the delta that moves unwrapped nodes to their new parent or `null` if there are no operations in the delta.
  32. *
  33. * @protected
  34. * @type {module:engine/model/operation/moveoperation~MoveOperation|null}
  35. */
  36. get _moveOperation() {
  37. return this.operations[ 0 ] || null;
  38. }
  39. /**
  40. * @inheritDoc
  41. */
  42. get _reverseDeltaClass() {
  43. return WrapDelta;
  44. }
  45. /**
  46. * @inheritDoc
  47. */
  48. static get className() {
  49. return 'engine.model.delta.UnwrapDelta';
  50. }
  51. /**
  52. * @inheritDoc
  53. */
  54. static get _priority() {
  55. return 10;
  56. }
  57. }
  58. /**
  59. * Unwraps given element, that is moves all it's children before it and then removes it. Throws
  60. * error if you try to unwrap an element that does not have a parent.
  61. *
  62. * @chainable
  63. * @method module:engine/model/batch~Batch#unwrap
  64. * @param {module:engine/model/element~Element} position Element to unwrap.
  65. */
  66. register( 'unwrap', function( element ) {
  67. if ( element.parent === null ) {
  68. /**
  69. * Trying to unwrap an element that has no parent.
  70. *
  71. * @error batch-unwrap-element-no-parent
  72. */
  73. throw new CKEditorError( 'batch-unwrap-element-no-parent: Trying to unwrap an element that has no parent.' );
  74. }
  75. const delta = new UnwrapDelta();
  76. this.addDelta( delta );
  77. let sourcePosition = Position.createFromParentAndOffset( element, 0 );
  78. const move = new MoveOperation( sourcePosition, element.maxOffset, Position.createBefore( element ), this.document.version );
  79. move.isSticky = true;
  80. delta.addOperation( move );
  81. this.document.applyOperation( move );
  82. // Computing new position because we moved some nodes before `element`.
  83. // If we would cache `Position.createBefore( element )` we remove wrong node.
  84. const remove = new RemoveOperation( Position.createBefore( element ), 1, this.document.version );
  85. delta.addOperation( remove );
  86. this.document.applyOperation( remove );
  87. return this;
  88. } );
  89. DeltaFactory.register( UnwrapDelta );