mediawiki-extensions-Visual.../modules/ve/dm/ve.dm.BranchNode.js
Ed Sanders edcaaf9edc Use static.name once for ce and dm nodes
Add a static.name property to ce nodes and make sure both ce
and dm nodes always use the static.name property in constructors
and registration calls.

The result of this is that any given node type should now only
appear once in the code as a string.

Bug: 45701
Change-Id: Ibf31de16ab28ad58209c1443cd74f93dda278998
2013-03-07 17:19:39 -08:00

147 lines
3.3 KiB
JavaScript

/*!
* VisualEditor DataModel BranchNode class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* DataModel branch node.
*
* Branch nodes can have branch or leaf nodes as children.
*
* @abstract
* @extends ve.dm.Node
* @mixins ve.BranchNode
* @constructor
* @param {ve.dm.Node[]} [children] Child nodes to attach
* @param {Object} [element] Reference to element in linear model
*/
ve.dm.BranchNode = function VeDmBranchNode( children, element ) {
// Mixin constructor
ve.BranchNode.call( this );
// Parent constructor
ve.dm.Node.call( this, 0, element );
if ( ve.isArray( children ) && children.length ) {
this.splice.apply( this, [0, 0].concat( children ) );
}
};
/**
* @event splice
* @see #method-splice
* @param {number} index
* @param {number} howmany
* @param {ve.dm.BranchNode} [childModel]
*/
/**
* @event update
*/
/* Inheritance */
ve.inheritClass( ve.dm.BranchNode, ve.dm.Node );
ve.mixinClass( ve.dm.BranchNode, ve.BranchNode );
/* Methods */
/**
* Add a child node to the end of the list.
*
* @method
* @param {ve.dm.BranchNode} childModel Item to add
* @returns {number} New number of children
* @emits splice
* @emits update
*/
ve.dm.BranchNode.prototype.push = function ( childModel ) {
this.splice( this.children.length, 0, childModel );
return this.children.length;
};
/**
* Remove a child node from the end of the list.
*
* @method
* @returns {ve.dm.BranchNode} Removed childModel
* @emits splice
* @emits update
*/
ve.dm.BranchNode.prototype.pop = function () {
if ( this.children.length ) {
var childModel = this.children[this.children.length - 1];
this.splice( this.children.length - 1, 1 );
return childModel;
}
};
/**
* Add a child node to the beginning of the list.
*
* @method
* @param {ve.dm.BranchNode} childModel Item to add
* @returns {number} New number of children
* @emits splice
* @emits update
*/
ve.dm.BranchNode.prototype.unshift = function ( childModel ) {
this.splice( 0, 0, childModel );
return this.children.length;
};
/**
* Remove a child node from the beginning of the list.
*
* @method
* @returns {ve.dm.BranchNode} Removed childModel
* @emits splice
* @emits update
*/
ve.dm.BranchNode.prototype.shift = function () {
if ( this.children.length ) {
var childModel = this.children[0];
this.splice( 0, 1 );
return childModel;
}
};
/**
* Add and/or remove child nodes at an offset.
*
* @method
* @param {number} index Index to remove and or insert nodes at
* @param {number} howmany Number of nodes to remove
* @param {ve.dm.BranchNode...} [nodes] Variadic list of nodes to insert
* @returns {ve.dm.BranchNode[]} Removed nodes
* @emits splice
*/
ve.dm.BranchNode.prototype.splice = function () {
var i,
length,
removals,
args = Array.prototype.slice.call( arguments ),
diff = 0;
if ( args.length >= 3 ) {
length = args.length;
for ( i = 2; i < length; i++ ) {
args[i].attach( this );
diff += args[i].getOuterLength();
}
}
removals = this.children.splice.apply( this.children, args );
for ( i = 0, length = removals.length; i < length; i++ ) {
removals[i].detach();
diff -= removals[i].getOuterLength();
}
this.adjustLength( diff, true );
this.emit.apply( this, ['splice'].concat( args ) );
return removals;
};