rootattributeoperation.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module engine/model/operation/rootattributeoperation
  7. */
  8. import Operation from './operation';
  9. import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
  10. /**
  11. * Operation to change root element's attribute. Using this class you can add, remove or change value of the attribute.
  12. *
  13. * This operation is needed, because root elements can't be changed through
  14. * @link module:engine/model/operation/attributeoperation~AttributeOperation}.
  15. * It is because {@link module:engine/model/operation/attributeoperation~AttributeOperation}
  16. * requires a range to change and root element can't
  17. * be a part of range because every {@link module:engine/model/position~Position} has to be inside a root.
  18. * {@link module:engine/model/position~Position} can't be created before a root element.
  19. *
  20. * @extends module:engine/model/operation/operation~Operation
  21. */
  22. export default class RootAttributeOperation extends Operation {
  23. /**
  24. * Creates an operation that changes, removes or adds attributes on root element.
  25. *
  26. * @see module:engine/model/operation/attributeoperation~AttributeOperation
  27. * @param {module:engine/model/rootelement~RootElement} root Root element to change.
  28. * @param {String} key Key of an attribute to change or remove.
  29. * @param {*} oldValue Old value of the attribute with given key or `null` if adding a new attribute.
  30. * @param {*} newValue New value to set for the attribute. If `null`, then the operation just removes the attribute.
  31. * @param {Number} baseVersion {@link module:engine/model/document~Document#version} on which the operation can be applied.
  32. */
  33. constructor( root, key, oldValue, newValue, baseVersion ) {
  34. super( baseVersion );
  35. /**
  36. * Root element to change.
  37. *
  38. * @readonly
  39. * @member {module:engine/model/rootelement~RootElement}
  40. */
  41. this.root = root;
  42. /**
  43. * Key of an attribute to change or remove.
  44. *
  45. * @readonly
  46. * @member {String}
  47. */
  48. this.key = key;
  49. /**
  50. * Old value of the attribute with given key or `null` if adding a new attribute.
  51. *
  52. * @readonly
  53. * @member {*}
  54. */
  55. this.oldValue = oldValue;
  56. /**
  57. * New value to set for the attribute. If `null`, then the operation just removes the attribute.
  58. *
  59. * @readonly
  60. * @member {*}
  61. */
  62. this.newValue = newValue;
  63. }
  64. get type() {
  65. if ( this.oldValue === null ) {
  66. return 'addRootAttribute';
  67. } else if ( this.newValue === null ) {
  68. return 'removeRootAttribute';
  69. } else {
  70. return 'changeRootAttribute';
  71. }
  72. }
  73. /**
  74. * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation}
  75. */
  76. clone() {
  77. return new RootAttributeOperation( this.root, this.key, this.oldValue, this.newValue, this.baseVersion );
  78. }
  79. /**
  80. * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation}
  81. */
  82. getReversed() {
  83. return new RootAttributeOperation( this.root, this.key, this.newValue, this.oldValue, this.baseVersion + 1 );
  84. }
  85. _execute() {
  86. if ( this.oldValue !== null && this.root.getAttribute( this.key ) !== this.oldValue ) {
  87. /**
  88. * The attribute which should be removed does not exists for the given node.
  89. *
  90. * @error rootattribute-operation-wrong-old-value
  91. * @param {module:engine/model/rootelement~RootElement} root
  92. * @param {String} key
  93. * @param {*} value
  94. */
  95. throw new CKEditorError(
  96. 'rootattribute-operation-wrong-old-value: Changed node has different attribute value than operation\'s old attribute value.',
  97. { root: this.root, key: this.key }
  98. );
  99. }
  100. if ( this.oldValue === null && this.newValue !== null && this.root.hasAttribute( this.key ) ) {
  101. /**
  102. * The attribute with given key already exists for the given node.
  103. *
  104. * @error rootattribute-operation-attribute-exists
  105. * @param {module:engine/model/rootelement~RootElement} root
  106. * @param {String} key
  107. */
  108. throw new CKEditorError(
  109. 'rootattribute-operation-attribute-exists: The attribute with given key already exists.',
  110. { root: this.root, key: this.key }
  111. );
  112. }
  113. if ( this.newValue !== null ) {
  114. this.root.setAttribute( this.key, this.newValue );
  115. } else {
  116. this.root.removeAttribute( this.key );
  117. }
  118. return { root: this.root, key: this.key, oldValue: this.oldValue, newValue: this.newValue };
  119. }
  120. /**
  121. * @inheritDoc
  122. */
  123. static get className() {
  124. return 'engine.model.operation.RootAttributeOperation';
  125. }
  126. /**
  127. * Creates RootAttributeOperation object from deserilized object, i.e. from parsed JSON string.
  128. *
  129. * @param {Object} json Deserialized JSON object.
  130. * @param {module:engine/model/document~Document} document Document on which this operation will be applied.
  131. * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation}
  132. */
  133. static fromJSON( json, document ) {
  134. if ( !document.hasRoot( json.root ) ) {
  135. /**
  136. * Cannot create RootAttributeOperation for document. Root with specified name does not exist.
  137. *
  138. * @error rootattributeoperation-fromjson-no-root
  139. * @param {String} rootName
  140. */
  141. throw new CKEditorError(
  142. 'rootattribute-operation-fromjson-no-root: Cannot create RootAttributeOperation. Root with specified name does not exist.',
  143. { rootName: json }
  144. );
  145. }
  146. return new RootAttributeOperation( document.getRoot( json.root ), json.key, json.oldValue, json.newValue, json.baseVersion );
  147. }
  148. }