mediawiki-extensions-Visual.../modules/es/bases/es.DocumentModelNode.js

224 lines
5.3 KiB
JavaScript

/**
* Creates an es.DocumentModelNode object.
*
* @class
* @abstract
* @constructor
* @extends {es.DocumentNode}
* @param {String} type Symbolic name of node type
* @param {Object} element Element object in document data
* @param {Integer} [length] Length of content data in document
*/
es.DocumentModelNode = function( type, element, length ) {
// Inheritance
es.DocumentNode.call( this );
// Properties
this.type = type;
this.parent = null;
this.root = this;
this.element = element || null;
this.contentLength = length || 0;
};
/* Abstract Methods */
/**
* Creates a view for this node.
*
* @abstract
* @method
* @returns {es.DocumentViewNode} New item view associated with this model
*/
es.DocumentModelNode.prototype.createView = function() {
throw 'DocumentModelNode.createView not implemented in this subclass:' + this.constructor;
};
/**
* Gets a plain object representation of the document's data.
*
* @method
* @returns {Object} Plain object representation
*/
es.DocumentModelNode.prototype.getPlainObject = function() {
throw 'DocumentModelNode.getPlainObject not implemented in this subclass:' + this.constructor;
};
/* Methods */
/**
* Gets the content length.
*
* @method
* @see {es.DocumentNode.prototype.getContentLength}
* @returns {Integer} Length of content
*/
es.DocumentModelNode.prototype.getContentLength = function() {
return this.contentLength;
};
/**
* Gets the element length.
*
* @method
* @see {es.DocumentNode.prototype.getElementLength}
* @returns {Integer} Length of content
*/
es.DocumentModelNode.prototype.getElementLength = function() {
return this.contentLength + 2;
};
/**
* Sets the content length.
*
* @method
* @param {Integer} contentLength Length of content
* @throws Invalid content length error if contentLength is less than 0
*/
es.DocumentModelNode.prototype.setContentLength = function( contentLength ) {
if ( contentLength < 0 ) {
throw 'Invalid content length error. Content length can not be less than 0.';
}
var diff = contentLength - this.contentLength;
this.contentLength = contentLength;
if ( this.parent ) {
this.parent.adjustContentLength( diff );
}
};
/**
* Adjust the content length.
*
* @method
* @param {Integer} adjustment Amount to adjust content length by
* @throws Invalid adjustment error if resulting length is less than 0
*/
es.DocumentModelNode.prototype.adjustContentLength = function( adjustment, quiet ) {
this.contentLength += adjustment;
// Make sure the adjustment was sane
if ( this.contentLength < 0 ) {
// Reverse the adjustment
this.contentLength -= adjustment;
// Complain about it
throw 'Invalid adjustment error. Content length can not be less than 0.';
}
if ( this.parent ) {
this.parent.adjustContentLength( adjustment, true );
}
if ( !quiet ) {
this.emit( 'update' );
}
};
/**
* Attaches this node to another as a child.
*
* @method
* @param {es.DocumentModelNode} parent Node to attach to
* @emits attach (parent)
*/
es.DocumentModelNode.prototype.attach = function( parent ) {
this.emit( 'beforeAttach', parent );
this.parent = parent;
this.setRoot( parent.getRoot() );
this.emit( 'afterAttach', parent );
};
/**
* Detaches this node from it's parent.
*
* @method
* @emits detach
*/
es.DocumentModelNode.prototype.detach = function() {
this.emit( 'beforeDetach' );
this.parent = null;
this.clearRoot();
this.emit( 'afterDetach' );
};
/**
* Gets a reference to this node's parent.
*
* @method
* @returns {es.DocumentModelNode} Reference to this node's parent
*/
es.DocumentModelNode.prototype.getParent = function() {
return this.parent;
};
/**
* Gets the root node in the tree this node is currently attached to.
*
* @method
* @returns {es.DocumentModelNode} Root node
*/
es.DocumentModelNode.prototype.getRoot = function() {
return this.root;
};
/**
* Sets the root node to this and all of it's children.
*
* This method is overridden by nodes with children.
*
* @method
* @param {es.DocumentModelNode} root Node to use as root
*/
es.DocumentModelNode.prototype.setRoot = function( root ) {
this.root = root;
};
/**
* Clears the root node from this and all of it's children.
*
* This method is overridden by nodes with children.
*
* @method
*/
es.DocumentModelNode.prototype.clearRoot = function() {
this.root = null;
};
/**
* Gets the element object.
*
* @method
* @returns {Object} Element object in linear data model
*/
es.DocumentModelNode.prototype.getElement = function() {
return this.element;
};
/**
* Gets the symbolic element type name.
*
* @method
* @returns {String} Symbolic name of element type
*/
es.DocumentModelNode.prototype.getElementType = function() {
//return this.element.type;
// We can't use this.element.type because this.element may be null
// So this function now returns this.type and should really be called
// getType()
// TODO: Do we care?
return this.type;
};
/**
* Gets an element attribute value.
*
* @method
* @returns {Mixed} Value of attribute, or null if no such attribute exists
*/
es.DocumentModelNode.prototype.getElementAttribute = function( key ) {
if ( this.element && this.element.attributes && key in this.element.attributes ) {
return this.element.attributes[key];
}
return null;
};
/* Inheritance */
es.extendClass( es.DocumentModelNode, es.DocumentNode );