mediawiki-extensions-Visual.../modules/ve/ve.Node.js

109 lines
2.7 KiB
JavaScript

/**
* Creates an ve.Node object.
*
* @class
* @abstract
* @constructor
* @extends {ve.EventEmitter}
*/
ve.Node = function() {
// Inheritance
ve.EventEmitter.call( this );
// Reusable function for passing update events upstream
var _this = this;
this.emitUpdate = function() {
_this.emit( 'update' );
};
};
/* Methods */
/**
* Gets the content length.
*
* @method
* @abstract
* @returns {Integer} Length of content
*/
ve.Node.prototype.getContentLength = function() {
throw 'DocumentNode.getContentLength not implemented in this subclass:' + this.constructor;
};
/**
* Gets the element length.
*
* @method
* @abstract
* @returns {Integer} Length of content
*/
ve.Node.prototype.getElementLength = function() {
throw 'DocumentNode.getElementLength not implemented in this subclass:' + this.constructor;
};
/**
* Checks if this node has child nodes.
*
* @method
* @abstract
* @returns {Boolean} Whether this node has children
*/
ve.Node.prototype.hasChildren = function() {
throw 'DocumentNode.hasChildren not implemented in this subclass:' + this.constructor;
};
/**
* Traverse tree of nodes (model or view) upstream and for each traversed node call callback function passing traversed node as a parameter.
* Callback function is called for node passed as node paramter as well.
*
* @param {ve.Node} node Node from which to start traversing
* @param {function} callback Callback method to be called for every traversed node
* @method
*/
ve.Node.traverseUpstream = function( node, callback ) {
while ( node ) {
if ( callback ( node ) === false ) {
break;
}
node = node.getParent();
}
};
/**
* Find the common ancestor of two equal-depth nodes, and return the
* path from each node to the common ancestor.
* @param {ve.Node} node1
* @param {ve.Node} node2
* @returns {Object|Boolean} Object with keys 'commonAncestor', 'node1Path' and 'node2Path',
* or false if there is no common ancestor or if the nodes have unequal depth
*/
ve.Node.getCommonAncestorPaths = function( node1, node2 ) {
var path1 = [],
path2 = [],
n1 = node1,
n2 = node2;
// Move up from n1 and n2 simultaneously until we find the
// common ancestor
while ( n1 !== n2 ) {
// Add these nodes to their respective paths
path1.push( n1 );
path2.push( n2 );
// Move up
n1 = n1.getParent();
n2 = n2.getParent();
if ( n1 === null || n2 === null ) {
// Reached a root, so no common ancestor or unequal depth
return false;
}
}
// If we got here, we've found the common ancestor, and because we did
// simultaneous traversal we also know node1 and node2 have the same depth.
return { 'commonAncestor': n1, 'node1Path': path1, 'node2Path': path2 };
};
/* Inheritance */
ve.extendClass( ve.Node, ve.EventEmitter );