2013-03-20 22:35:05 +00:00
|
|
|
/*!
|
|
|
|
* VisualEditor MetaLinearData class.
|
|
|
|
*
|
|
|
|
* Class containing meta linear data and an index-value store.
|
|
|
|
*
|
|
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Meta linear data storage
|
|
|
|
*
|
|
|
|
* @class
|
|
|
|
* @extends ve.dm.LinearData
|
|
|
|
* @constructor
|
|
|
|
* @param {ve.dm.IndexValueStore} store Index-value store
|
|
|
|
* @param {Array} [data] Linear data
|
|
|
|
*/
|
|
|
|
ve.dm.MetaLinearData = function VeDmMetaLinearData( store, data ) {
|
|
|
|
ve.dm.LinearData.call( this, store, data );
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Inheritance */
|
|
|
|
|
|
|
|
ve.inheritClass( ve.dm.MetaLinearData, ve.dm.LinearData );
|
|
|
|
|
2013-04-06 16:45:26 +00:00
|
|
|
/* Static Methods */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes an array of meta linear data arrays and collapses them into a single array.
|
|
|
|
*
|
|
|
|
* Undefined values will be discarded e.g.
|
|
|
|
* [ [ metaItem1, metaItem2 ], undefined, [ metaItem3 ], undefined ]
|
|
|
|
* =>
|
|
|
|
* [ [ metaItem1, metaItem2, metaItem3 ] ]
|
|
|
|
*
|
|
|
|
* @static
|
|
|
|
* @param {Array} data Meta linear data arrays
|
|
|
|
* @returns {Array} Merged data
|
|
|
|
*/
|
|
|
|
ve.dm.MetaLinearData.static.merge = function ( data ) {
|
ve.dm.Transaction: Implement newFromDocumentInsertion
This function builds a transaction that takes a document slice and
inserts it back into the document it came from, applying any changes
that were made.
This makes editing document slices simple:
slicedDoc = doc.getDocumentSlice( captionNode );
// Edit slicedDoc using a surface
tx = ve.dm.Transaction.newFromDocumentInsertion( doc, captionNode, slicedDoc );
surface.change( tx );
Specifically, newFromDocumentInsertion replaces the node's contents
with the document's contents (meaning any changes made to the node in
the meantime are lost). It also merges the stores internal lists
of the two documents and remaps indexes accordingly. This means editing
of references inside of references is supported.
This functionality is not specific to slices, and can also be used to
safely insert data from a paste buffer, with internal list data being
transplanted correctly.
ve.dm.MetaLinearData:
* Make merge( [ undefined, undefined, ... ] ) return undefined rather
than [].
ve.dm.Document:
* In getDocumentSlice, store a pointer to the original dm.Document in
the new one, and also store the length of the internal list. This
allows us to figure out which internal list items the two documents
have in common when we insert the modified slice back into the main
document.
* In getMetadataReplace, optionally take the inserted metadata as a
parameter, to allow for operations that insert both data and metadata.
Per Ed's review, rewrite this function to return null rather than {}
if no metadata needs to be replaced.
ve.dm.InternalList:
* Add method to merge two internal lists
ve.dm.Transaction:
* Remove newFromNodeReplacement and replace it with newFromDocumentInsertion.
* In pushReplace, optionally take the inserted metadata as a parameter.
Change-Id: I786ee7bad796aa54bc242993b4de3ad18ad0773e
2013-05-22 15:06:25 +00:00
|
|
|
var i, merged = [], allUndefined = true;
|
2013-04-06 16:45:26 +00:00
|
|
|
for ( i = 0; i < data.length; i++ ) {
|
|
|
|
if ( data[i] !== undefined ) {
|
ve.dm.Transaction: Implement newFromDocumentInsertion
This function builds a transaction that takes a document slice and
inserts it back into the document it came from, applying any changes
that were made.
This makes editing document slices simple:
slicedDoc = doc.getDocumentSlice( captionNode );
// Edit slicedDoc using a surface
tx = ve.dm.Transaction.newFromDocumentInsertion( doc, captionNode, slicedDoc );
surface.change( tx );
Specifically, newFromDocumentInsertion replaces the node's contents
with the document's contents (meaning any changes made to the node in
the meantime are lost). It also merges the stores internal lists
of the two documents and remaps indexes accordingly. This means editing
of references inside of references is supported.
This functionality is not specific to slices, and can also be used to
safely insert data from a paste buffer, with internal list data being
transplanted correctly.
ve.dm.MetaLinearData:
* Make merge( [ undefined, undefined, ... ] ) return undefined rather
than [].
ve.dm.Document:
* In getDocumentSlice, store a pointer to the original dm.Document in
the new one, and also store the length of the internal list. This
allows us to figure out which internal list items the two documents
have in common when we insert the modified slice back into the main
document.
* In getMetadataReplace, optionally take the inserted metadata as a
parameter, to allow for operations that insert both data and metadata.
Per Ed's review, rewrite this function to return null rather than {}
if no metadata needs to be replaced.
ve.dm.InternalList:
* Add method to merge two internal lists
ve.dm.Transaction:
* Remove newFromNodeReplacement and replace it with newFromDocumentInsertion.
* In pushReplace, optionally take the inserted metadata as a parameter.
Change-Id: I786ee7bad796aa54bc242993b4de3ad18ad0773e
2013-05-22 15:06:25 +00:00
|
|
|
allUndefined = false;
|
2013-04-06 16:45:26 +00:00
|
|
|
merged = merged.concat( data[i] );
|
|
|
|
}
|
|
|
|
}
|
ve.dm.Transaction: Implement newFromDocumentInsertion
This function builds a transaction that takes a document slice and
inserts it back into the document it came from, applying any changes
that were made.
This makes editing document slices simple:
slicedDoc = doc.getDocumentSlice( captionNode );
// Edit slicedDoc using a surface
tx = ve.dm.Transaction.newFromDocumentInsertion( doc, captionNode, slicedDoc );
surface.change( tx );
Specifically, newFromDocumentInsertion replaces the node's contents
with the document's contents (meaning any changes made to the node in
the meantime are lost). It also merges the stores internal lists
of the two documents and remaps indexes accordingly. This means editing
of references inside of references is supported.
This functionality is not specific to slices, and can also be used to
safely insert data from a paste buffer, with internal list data being
transplanted correctly.
ve.dm.MetaLinearData:
* Make merge( [ undefined, undefined, ... ] ) return undefined rather
than [].
ve.dm.Document:
* In getDocumentSlice, store a pointer to the original dm.Document in
the new one, and also store the length of the internal list. This
allows us to figure out which internal list items the two documents
have in common when we insert the modified slice back into the main
document.
* In getMetadataReplace, optionally take the inserted metadata as a
parameter, to allow for operations that insert both data and metadata.
Per Ed's review, rewrite this function to return null rather than {}
if no metadata needs to be replaced.
ve.dm.InternalList:
* Add method to merge two internal lists
ve.dm.Transaction:
* Remove newFromNodeReplacement and replace it with newFromDocumentInsertion.
* In pushReplace, optionally take the inserted metadata as a parameter.
Change-Id: I786ee7bad796aa54bc242993b4de3ad18ad0773e
2013-05-22 15:06:25 +00:00
|
|
|
return allUndefined ? [ undefined ] : [ merged ];
|
2013-04-06 16:45:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Methods */
|
|
|
|
|
2013-03-20 22:35:05 +00:00
|
|
|
/**
|
|
|
|
* Gets linear data from specified index(es).
|
|
|
|
*
|
|
|
|
* If either index is omitted the array at that point is returned
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {number} [offset] Offset to get data from
|
|
|
|
* @param {number} [metadataOffset] Index to get data from
|
|
|
|
* @returns {Object|Array} Data from index(es), or all data (by reference)
|
|
|
|
*/
|
|
|
|
ve.dm.MetaLinearData.prototype.getData = function ( offset, metadataOffset ) {
|
|
|
|
if ( offset === undefined ) {
|
|
|
|
return this.data;
|
|
|
|
} else if ( metadataOffset === undefined ) {
|
|
|
|
return this.data[offset];
|
|
|
|
} else {
|
|
|
|
return this.data[offset] === undefined ? undefined : this.data[offset][metadataOffset];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets number of metadata elements at specified offset.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {number} offset Offset to count metadata at
|
|
|
|
* @returns {number} Number of metadata elements at specified offset
|
|
|
|
*/
|
|
|
|
ve.dm.MetaLinearData.prototype.getDataLength = function ( offset ) {
|
|
|
|
return this.data[offset] === undefined ? 0 : this.data[offset].length;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets number of metadata elements in the entire object.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {number} Number of metadata elements in the entire object
|
|
|
|
*/
|
|
|
|
ve.dm.MetaLinearData.prototype.getTotalDataLength = function () {
|
|
|
|
var n = 0, i = this.getLength();
|
|
|
|
while ( i-- ) {
|
|
|
|
n += this.getDataLength( i );
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
};
|