8
0

attributeoperation.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 Operation from './operation.js';
  7. import Range from '../range.js';
  8. import CKEditorError from '../../ckeditorerror.js';
  9. import TextFragment from '../textfragment.js';
  10. /**
  11. * Operation to change nodes' attribute. Using this class you can add, remove or change value of the attribute.
  12. *
  13. * @class treeModel.operation.AttributeOperation
  14. */
  15. export default class AttributeOperation extends Operation {
  16. /**
  17. * Creates an operation that changes, removes or adds attributes.
  18. *
  19. * If only the new attribute is set, then it will be inserted. Note that in all nodes in ranges there must be
  20. * no attributes with the same key as the new attribute.
  21. *
  22. * If only the old attribute is set, then it will be removed. Note that this attribute must be present in all nodes in
  23. * ranges.
  24. *
  25. * If both new and old attributes are set, then the operation will change the attribute value. Note that both new and
  26. * old attributes have to have the same key and the old attribute must be present in all nodes in ranges.
  27. *
  28. * @param {treeModel.Range} range Range on which the operation should be applied.
  29. * @param {String} key Key of an attribute to change or remove.
  30. * @param {*} oldValue Old value of the attribute with given key or `null` if adding a new attribute.
  31. * @param {*} newValue New value to set for the attribute. If `null`, then the operation just removes the attribute.
  32. * @param {Number} baseVersion {@link treeModel.Document#version} on which the operation can be applied.
  33. * @constructor
  34. */
  35. constructor( range, key, oldValue, newValue, baseVersion ) {
  36. super( baseVersion );
  37. /**
  38. * Range on which operation should be applied.
  39. *
  40. * @readonly
  41. * @type {treeModel.Range}
  42. */
  43. this.range = Range.createFromRange( range );
  44. /**
  45. * Key of an attribute to change or remove.
  46. *
  47. * @readonly
  48. * @property {String} key
  49. */
  50. this.key = key;
  51. /**
  52. * Old value of the attribute with given key or `null` if adding a new attribute.
  53. *
  54. * @readonly
  55. * @property {*} oldValue
  56. */
  57. this.oldValue = oldValue;
  58. /**
  59. * New value to set for the attribute. If `null`, then the operation just removes the attribute.
  60. *
  61. * @readonly
  62. * @property {*} newValue
  63. */
  64. this.newValue = newValue;
  65. }
  66. get type() {
  67. return 'attr';
  68. }
  69. clone() {
  70. return new AttributeOperation( this.range, this.key, this.oldValue, this.newValue, this.baseVersion );
  71. }
  72. getReversed() {
  73. return new AttributeOperation( this.range, this.key, this.newValue, this.oldValue, this.baseVersion + 1 );
  74. }
  75. _execute() {
  76. for ( let item of this.range.getAllNodes( true ) ) {
  77. if ( this.oldValue !== null && item.getAttribute( this.key ) !== this.oldValue ) {
  78. /**
  79. * The attribute which should be removed does not exists for the given node.
  80. *
  81. * @error operation-attribute-no-attr-to-remove
  82. * @param {treeModel.Node} node
  83. * @param {String} key
  84. * @param {*} value
  85. */
  86. throw new CKEditorError(
  87. 'operation-attribute-no-attr-to-remove: The attribute which should be removed does not exists for given node.',
  88. { node: item, key: this.key, value: this.oldValue }
  89. );
  90. }
  91. if ( this.oldValue === null && this.newValue !== null && item.hasAttribute( this.key ) ) {
  92. /**
  93. * The attribute with given key already exists for the given node.
  94. *
  95. * @error operation-attribute-attr-exists
  96. * @param {treeModel.Node} node
  97. * @param {String} key
  98. */
  99. throw new CKEditorError(
  100. 'operation-attribute-attr-exists: The attribute with given key already exists.',
  101. { node: item, key: this.key }
  102. );
  103. }
  104. if ( item instanceof TextFragment ) {
  105. item.commonParent._children.setAttribute( item.first.getIndex(), item.text.length, this.key, this.newValue );
  106. }
  107. else {
  108. if ( this.newValue !== null ) {
  109. item.setAttribute( this.key, this.newValue );
  110. } else {
  111. item.removeAttribute( this.key );
  112. }
  113. }
  114. }
  115. return { range: this.range, key: this.key, oldValue: this.oldValue, newValue: this.newValue };
  116. }
  117. }