Преглед изворни кода

Add attribute manipulation API to engine.treeModel.TextFragment.

Szymon Cofalik пре 9 година
родитељ
комит
25b930caa3

+ 4 - 9
packages/ckeditor5-engine/src/treemodel/operation/attributeoperation.js

@@ -120,15 +120,10 @@ export default class AttributeOperation extends Operation {
 				);
 				);
 			}
 			}
 
 
-			if ( item instanceof TextFragment ) {
-				item.commonParent._children.setAttribute( item.first.getIndex(), item.text.length, this.key, this.newValue );
-			}
-			else {
-				if ( this.newValue !== null ) {
-					item.setAttribute( this.key, this.newValue );
-				} else {
-					item.removeAttribute( this.key );
-				}
+			if ( this.newValue !== null ) {
+				item.setAttribute( this.key, this.newValue );
+			} else {
+				item.removeAttribute( this.key );
 			}
 			}
 		}
 		}
 
 

+ 67 - 0
packages/ckeditor5-engine/src/treemodel/textfragment.js

@@ -6,12 +6,18 @@
 'use strict';
 'use strict';
 
 
 import CharacterProxy from './characterproxy.js';
 import CharacterProxy from './characterproxy.js';
+import utils from '../../utils/utils.js';
 
 
 /**
 /**
  * TextFragment is an aggregator for multiple CharacterProxy instances that are placed next to each other in
  * TextFragment is an aggregator for multiple CharacterProxy instances that are placed next to each other in
  * tree model, in the same parent, and all have same attributes set. Instances of this class are created and returned
  * tree model, in the same parent, and all have same attributes set. Instances of this class are created and returned
  * in various algorithms that "merge characters" (see {@link engine.treeModel.TreeWalker}, {@link engine.treeModel.Range}).
  * in various algorithms that "merge characters" (see {@link engine.treeModel.TreeWalker}, {@link engine.treeModel.Range}).
  *
  *
+ * **Note:** TextFragment instances are created on the fly basing on the current state of tree model and attributes
+ * set on characters. Because of this it is highly unrecommended to store references to TextFragment instances
+ * because they might get invalidated due to operations on Document. This is especially true when you change
+ * attributes of TextFragment.
+ *
  * Difference between {@link engine.treeModel.TextFragment} and {@link engine.treeModel.Text} is that the former is a set of
  * Difference between {@link engine.treeModel.TextFragment} and {@link engine.treeModel.Text} is that the former is a set of
  * nodes taken from tree model, while {@link engine.treeModel.Text} is simply a string with attributes set.
  * nodes taken from tree model, while {@link engine.treeModel.Text} is simply a string with attributes set.
  *
  *
@@ -105,4 +111,65 @@ export default class TextFragment {
 	getAttributes() {
 	getAttributes() {
 		return this.first.getAttributes();
 		return this.first.getAttributes();
 	}
 	}
+
+	/**
+	 * Sets attribute on the text fragment. If attribute with the same key already is set, it overwrites its values.
+	 *
+	 * **Note:** Changing attributes of text fragment affects document state. This TextFragment instance properties
+	 * will be refreshed, but other may get invalidated. It is highly unrecommended to store references to TextFragment instances.
+	 *
+	 * @param {String} key Key of attribute to set.
+	 * @param {*} value Attribute value.
+	 */
+	setAttribute( key, value ) {
+		let index = this.first.getIndex();
+
+		this.commonParent._children.setAttribute( this.first.getIndex(), this.text.length, key, value );
+
+		this.first = this.commonParent.getChild( index );
+		this.last = this.getCharAt( this.text.length - 1 );
+	}
+
+	/**
+	 * Removes all attributes from the text fragment and sets given attributes.
+	 *
+	 * **Note:** Changing attributes of text fragment affects document state. This TextFragment instance properties
+	 * will be refreshed, but other may get invalidated. It is highly unrecommended to store references to TextFragment instances.
+	 *
+	 * @param {Iterable|Object} attrs Iterable object containing attributes to be set.
+	 * See {@link engine.treeModel.TextFragment#getAttributes}.
+	 */
+	setAttributesTo( attrs ) {
+		let attrsMap = utils.toMap( attrs );
+
+		this.clearAttributes();
+
+		for ( let attr of attrsMap ) {
+			this.setAttribute( attr[ 0 ], attr[ 1 ] );
+		}
+	}
+
+	/**
+	 * Removes an attribute with given key from the text fragment.
+	 *
+	 * **Note:** Changing attributes of text fragment affects document state. This TextFragment instance properties
+	 * will be refreshed, but other may get invalidated. It is highly unrecommended to store references to TextFragment instances.
+	 *
+	 * @param {String} key Key of attribute to remove.
+	 */
+	removeAttribute( key ) {
+		this.setAttribute( key, null );
+	}
+
+	/**
+	 * Removes all attributes from the text fragment.
+	 *
+	 * **Note:** Changing attributes of text fragment affects document state. This TextFragment instance properties
+	 * will be refreshed, but other may get invalidated. It is highly unrecommended to store references to TextFragment instances.
+	 */
+	clearAttributes() {
+		for ( let attr of this.getAttributes() ) {
+			this.removeAttribute( attr[ 0 ] );
+		}
+	}
 }
 }