/*!
* VisualEditor DataModel MetaList class.
*
* @copyright See AUTHORS.txt
*/
/**
* DataModel meta list.
*
* @class
* @mixes OO.EventEmitter
*
* @constructor
* @param {ve.dm.Document} doc Document model
*/
ve.dm.MetaList = function VeDmMetaList( doc ) {
// Mixin constructors
OO.EventEmitter.call( this );
this.doc = doc;
// Sorted array of attached ve.dm.MetaItem nodes in document order
this.items = [];
// The meta list is constructed before the model tree is built, so
// we don't need to initialise this item list, just listen to changes
this.doc.connect( this, {
nodeAttached: 'onNodeAttached',
nodeDetached: 'onNodeDetached'
} );
};
/* Inheritance */
OO.mixinClass( ve.dm.MetaList, OO.EventEmitter );
/* Events */
/**
* @event ve.dm.MetaList#insert
* @param {ve.dm.MetaItem} item Item that was inserted
*/
/**
* @event ve.dm.MetaList#remove
* @param {ve.dm.MetaItem} item Item that was removed
*/
/* Methods */
/**
* If a ve.dm.MetaItem was attached, insert it into items in document order
*
* @param {ve.dm.Node} node The node that was attached
*/
ve.dm.MetaList.prototype.onNodeAttached = function ( node ) {
const offsetPath = node.getOffsetPath();
if ( node instanceof ve.dm.MetaItem ) {
const i = OO.binarySearch( this.items, ( other ) => ve.compareTuples( offsetPath, other.getOffsetPath() ), true );
this.items.splice( i, 0, node );
this.emit( 'insert', node );
}
};
/**
* If a ve.dm.MetaItem was detached, remove it from items
*
* @param {ve.dm.Node} node The node that was detached
*/
ve.dm.MetaList.prototype.onNodeDetached = function ( node ) {
if ( node instanceof ve.dm.MetaItem ) {
const i = this.items.indexOf( node );
if ( i !== -1 ) {
this.items.splice( i, 1 );
this.emit( 'remove', node );
}
}
};
ve.dm.MetaList.prototype.indexOf = function ( item, group ) {
const items = group ? this.getItemsInGroup( group ) : this.items;
return items.indexOf( item );
};
/**
* Get all items in a group.
*
* This function returns a shallow copy, so the array isn't returned by reference but the items
* themselves are.
*
* @param {string} group
* @return {ve.dm.MetaItem[]} Array of items in the group (shallow copy)
*/
ve.dm.MetaList.prototype.getItemsInGroup = function ( group ) {
return this.items.filter( ( item ) => item.getGroup() === group );
};
/**
* Get all items in the list.
*
* This function returns a shallow copy, so the array isn't returned by reference but the items
* themselves are.
*
* @return {ve.dm.MetaItem[]} Array of items in the list
*/
ve.dm.MetaList.prototype.getItems = function () {
return this.items.slice();
};