Index: trunk/extensions/VisualEditor/modules/es/models/es.DocumentModel.js |
— | — | @@ -65,45 +65,47 @@ |
66 | 66 | * Each function is called in the context of a state, and takes an operation object as a parameter. |
67 | 67 | */ |
68 | 68 | es.DocumentModel.operations = ( function() { |
69 | | - function invalidate( from, to ) { |
70 | | - this.rebuild.push( { 'from': from, 'to': to } ); |
71 | | - } |
72 | | - |
73 | 69 | function retain( op ) { |
74 | 70 | annotate.call( this, this.cursor + op.length ); |
75 | 71 | this.cursor += op.length; |
76 | 72 | } |
77 | 73 | |
| 74 | + function rebuild( newData, oldNodes ) { |
| 75 | + var parent = oldNodes[0].getParent(), |
| 76 | + index = parent.indexOf( oldNodes[0] ); |
| 77 | + // Remove the node we are about to insert into from the model tree |
| 78 | + parent.splice( index, oldNodes.length ); |
| 79 | + // Regenerate nodes for the data we've affected |
| 80 | + var newNodes = es.DocumentModel.createNodesFromData( newData ); |
| 81 | + // Insert new elements into the tree where the old ones used to be |
| 82 | + for ( var i = newNodes.length; i >= 0; i-- ) { |
| 83 | + parent.splice( index, 0, newNodes[i] ); |
| 84 | + } |
| 85 | + } |
| 86 | + |
78 | 87 | function insert( op ) { |
79 | 88 | if ( es.DocumentModel.isStructuralOffset( this.data, this.cursor ) ) { |
80 | 89 | // TODO: Support tree updates when inserting between elements |
81 | 90 | } else { |
82 | 91 | // Get the node we are about to insert into |
83 | 92 | var node = this.tree.getNodeFromOffset( this.cursor ); |
| 93 | + if ( !node ) { |
| 94 | + throw 'Missing node error. A node could not not be found at the cursor.'; |
| 95 | + } |
84 | 96 | if ( es.DocumentModel.containsElementData( op.data ) ) { |
85 | | - var nodeParent = node.getParent(); |
86 | | - if ( !nodeParent ) { |
87 | | - throw 'Missing parent error. Node does not have a parent node.'; |
88 | | - } |
89 | | - var offset = this.tree.getOffsetFromNode( node ), |
90 | | - length = node.getElementLength() + op.data.length, |
91 | | - index = nodeParent.indexOf( node ); |
92 | | - if ( index === -1 ) { |
93 | | - throw 'Missing child error. Node could not be found in its parent node.'; |
94 | | - } |
95 | | - // Remove the node we are about to insert into from the model tree |
96 | | - nodeParent.splice( index, 1 ); |
97 | 97 | // Perform insert on linear data model |
98 | 98 | es.insertIntoArray( this.data, this.cursor, op.data ); |
99 | 99 | annotate.call( this, this.cursor + op.data.length ); |
100 | | - // Regenerate nodes for the data we've affected |
101 | | - var nodes = es.DocumentModel.createNodesFromData( |
102 | | - this.data.slice( offset, length ) |
103 | | - ); |
104 | | - // Insert new elements into the tree where the old one used to be |
105 | | - for ( var i = nodes.length; i >= 0; i-- ) { |
106 | | - this.tree.splice( index, nodes[i] ); |
| 100 | + // Synchronize model tree |
| 101 | + var offset = this.tree.getOffsetFromNode( node ); |
| 102 | + if ( offset === -1 ) { |
| 103 | + throw 'Invalid offset error. Node is not in model tree'; |
107 | 104 | } |
| 105 | + rebuild.call( |
| 106 | + this, |
| 107 | + this.data.slice( offset, offset + node.getElementLength() + op.data.length ), |
| 108 | + [node] |
| 109 | + ); |
108 | 110 | } else { |
109 | 111 | // Perform insert on linear data model |
110 | 112 | es.insertIntoArray( this.data, this.cursor, op.data ); |
— | — | @@ -1208,8 +1210,7 @@ |
1209 | 1211 | 'tree': this, |
1210 | 1212 | 'cursor': 0, |
1211 | 1213 | 'set': [], |
1212 | | - 'clear': [], |
1213 | | - 'rebuild': [] |
| 1214 | + 'clear': [] |
1214 | 1215 | }, |
1215 | 1216 | operations = transaction.getOperations(); |
1216 | 1217 | for ( var i = 0, length = operations.length; i < length; i++ ) { |
— | — | @@ -1220,7 +1221,6 @@ |
1221 | 1222 | throw 'Invalid operation error. Operation type is not supported: ' + operation.type; |
1222 | 1223 | } |
1223 | 1224 | } |
1224 | | - // TODO: Synchronize op.tree - insert elements and adjust lengths |
1225 | 1225 | }; |
1226 | 1226 | |
1227 | 1227 | /** |
— | — | @@ -1235,8 +1235,7 @@ |
1236 | 1236 | 'tree': this, |
1237 | 1237 | 'cursor': 0, |
1238 | 1238 | 'set': [], |
1239 | | - 'clear': [], |
1240 | | - 'rebuild': [] |
| 1239 | + 'clear': [] |
1241 | 1240 | }, |
1242 | 1241 | operations = transaction.getOperations(); |
1243 | 1242 | for ( var i = 0, length = operations.length; i < length; i++ ) { |
— | — | @@ -1247,7 +1246,6 @@ |
1248 | 1247 | throw 'Invalid operation error. Operation type is not supported: ' + operation.type; |
1249 | 1248 | } |
1250 | 1249 | } |
1251 | | - // TODO: Synchronize op.tree - insert elements and adjust lengths |
1252 | 1250 | }; |
1253 | 1251 | |
1254 | 1252 | /* Inheritance */ |
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentModelBranchNode.js |
— | — | @@ -200,6 +200,17 @@ |
201 | 201 | }; |
202 | 202 | |
203 | 203 | /** |
| 204 | + * Gets the index of a given child node. |
| 205 | + * |
| 206 | + * @method |
| 207 | + * @param {es.DocumentModelNode} node Child node to find index of |
| 208 | + * @returns {Integer} Index of child node or -1 if node was not found |
| 209 | + */ |
| 210 | +es.DocumentModelBranchNode.prototype.indexOf = function( node ) { |
| 211 | + return this.children.indexOf( node ); |
| 212 | +}; |
| 213 | + |
| 214 | +/** |
204 | 215 | * Sets the root node to this and all of it's children. |
205 | 216 | * |
206 | 217 | * @method |