Implement basic replace processor

* Implement basic TransactionProcessor.replace(), only does content
  replacements
* Add ve.dm.Document.containsElementData()
* Fix bug in attribute()
* Write basic tests for attribute() and replace()

Change-Id: Ie9c22aec3f2631be5b0bd66790408ad283565491
This commit is contained in:
Catrope 2012-05-04 11:07:55 -07:00
parent a9b26c8b55
commit 11a3b6886b
3 changed files with 87 additions and 2 deletions

View file

@ -65,6 +65,24 @@ ve.dm.Document.prototype.rebuildNodes = function( parent, index, numNodes, offse
return nodes;
};
/* Static methods */
/**
* Checks if elements are present within data.
*
* @static
* @method
* @param {Array} data Data to look for elements within
* @returns {Boolean} If elements exist in data
*/
ve.dm.Document.containsElementData = function( data ) {
for ( var i = 0, length = data.length; i < length; i++ ) {
if ( data[i].type !== undefined ) {
return true;
}
}
return false;
};
/* Inheritance */
ve.extendClass( ve.dm.Document, ve.dm.DocumentFragment );

View file

@ -169,7 +169,7 @@ ve.dm.TransactionProcessor.prototype.annotate = function( op ) {
* to: new attribute value, or undefined to unset
*/
ve.dm.TransactionProcessor.prototype.attribute = function( op ) {
var element = this.model.data[this.cursor];
var element = this.document.data[this.cursor];
if ( element.type === undefined ) {
throw 'Invalid element error. Can not set attributes on non-element data.';
}
@ -207,5 +207,26 @@ ve.dm.TransactionProcessor.prototype.attribute = function( op ) {
* replacement: Linear model data fragment to insert
*/
ve.dm.TransactionProcessor.prototype.replace = function( op ) {
// TODO
var remove = this.reversed ? op.replacement : op.remove,
replacement = this.reversed ? op.remove : op.replacement,
removeHasStructure = ve.dm.Document.containsElementData( remove ),
replacementHasStructure = ve.dm.Document.containsElementData( replacement ),
node;
// Figure out if this is a structural replacement or a content replacement
if ( !removeHasStructure && !replacementHasStructure ) {
// Content replacement
// Update the linear model
ve.batchSplice( this.document.data, this.cursor, remove.length, replacement );
this.applyAnnotations( this.cursor + replacement.length );
// Get the node containing the replaced content
node = this.document.getNodeFromOffset( this.cursor );
// Queue a resize for this node
//this.synchronizer.pushResize( node, replacement.length - remove.length );
// Advance the cursor
this.cursor += replacement.length;
} else {
// Structural replacement
// TODO implement
}
};

View file

@ -51,3 +51,49 @@ test( 'annotate', function() {
deepEqual( doc.getData(), ve.dm.example.data,
'Complex annotation transaction rolls back correctly' );
} );
test( 'attribute', function() {
var doc = new ve.dm.Document( ve.dm.example.data.slice( 0 ) );
var tx = new ve.dm.Transaction();
var expectedData = ve.dm.example.data.slice( 0 );
tx.pushReplaceElementAttribute( 'level', 1, 2 );
tx.pushRetain( 11 );
tx.pushReplaceElementAttribute( 'styles', ['bullet'], ['number'] );
expectedData[0].attributes.level = 2;
expectedData[11].attributes.styles = ['number'];
ve.dm.TransactionProcessor.commit( doc, tx );
deepEqual( doc.getData(), expectedData,
'Attribute transaction replaces attributes correctly' );
ve.dm.TransactionProcessor.rollback( doc, tx );
deepEqual( doc.getData(), ve.dm.example.data,
'Attribute transaction rolls back correctly' );
// TODO test attribute addition/removal
doc = new ve.dm.Document( ve.dm.example.data.slice( 0 ) );
tx = new ve.dm.Transaction();
tx.pushRetain( 1 );
tx.pushReplaceElementAttribute( 'foo', 23, 42 );
raises(
function() { ve.dm.TransactionProcessor.commit( doc, tx ); },
/^Invalid element error. Can not set attributes on non-element data.$/,
'Trying to replace attributes on content results in an exception'
);
} );
test( 'replace', function() {
var doc = new ve.dm.Document( ve.dm.example.data.slice( 0 ) );
var tx = new ve.dm.Transaction();
var expectedData = ve.dm.example.data.slice( 0 );
tx.pushRetain( 1 );
tx.pushReplace( [ 'a' ], [ 'F', 'O', 'O' ] );
expectedData.splice( 1, 1, 'F', 'O', 'O' );
ve.dm.TransactionProcessor.commit( doc, tx );
deepEqual( doc.getData(), expectedData,
'Replace transaction replaces content correctly' );
ve.dm.TransactionProcessor.rollback( doc, tx );
deepEqual( doc.getData(), ve.dm.example.data,
'Replace transaction rolls back correctly' );
} );