mediawiki-extensions-Visual.../modules/ve/dm/nodes/ve.dm.MWTemplateNode.js
Ed Sanders 3495c6f747 Clone template dom elements being sent to converter
The dom elements in the IV store are used for rendering, so if they
are sent by reference to the converter they get re-attached, causing
all templates to disappear from the page whenever you press 'review
and save'.

Fix is to run it through ve.copyArray, which clones all the nodes.

Change-Id: I1b03351a28ac82e0fdb7e94e761cf65d6548e501
2013-05-09 13:42:44 +01:00

134 lines
4.2 KiB
JavaScript

/*!
* VisualEditor DataModel MWTemplateNode class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* DataModel MediaWiki template node.
*
* @class
* @abstract
* @extends ve.dm.GeneratedContentNode
* @constructor
* @param {number} [length] Length of content data in document; ignored and overridden to 0
* @param {Object} [element] Reference to element in linear model
*/
ve.dm.MWTemplateNode = function VeDmMWTemplateNode( length, element ) {
// Parent constructor
ve.dm.GeneratedContentNode.call( this, 0, element );
};
/* Inheritance */
ve.inheritClass( ve.dm.MWTemplateNode, ve.dm.GeneratedContentNode );
/* Static members */
ve.dm.MWTemplateNode.static.name = 'MWtemplate';
ve.dm.MWTemplateNode.static.matchTagNames = null;
// We're interested in all nodes that have mw:Object/Template, even if they also have other mw:
// types. So we match all mw: types, then use a matchFunction to assert that mw:Object/Template
// is in there.
ve.dm.MWTemplateNode.static.matchRdfaTypes = [ 'mw:Object/Template', /^mw:/ ];
ve.dm.MWTemplateNode.static.matchFunction = function ( domElement ) {
return ve.indexOf( 'mw:Object/Template',
( domElement.getAttribute( 'typeof' ) || '' ).split( ' ' )
) !== -1;
};
ve.dm.MWTemplateNode.static.getHashObject = function ( dataElement ) {
return {
type: dataElement.type,
mw: dataElement.attributes.mw
};
};
ve.dm.MWTemplateNode.static.toDataElement = function ( domElements, converter ) {
var dataElement,
mw = JSON.parse( domElements[0].getAttribute( 'data-mw' ) ),
isInline = this.isHybridInline( domElements, converter ),
type = isInline ? 'MWtemplateInline' : 'MWtemplateBlock';
dataElement = {
'type': type,
'attributes': {
'mw': mw,
'mwOriginal': ve.copyObject( mw )
}
};
this.storeDomElements( dataElement, domElements, converter.getStore() );
return dataElement;
};
ve.dm.MWTemplateNode.static.toDomElements = function ( dataElement, doc, converter ) {
var span, index;
if ( ve.compareObjects( dataElement.attributes.mw, dataElement.attributes.mwOriginal ) ) {
// If the template is unchanged just send back the original dom elements so selser can skip over it
index = converter.getStore().indexOfHash( ve.getHash( this.getHashObject( dataElement ) ) );
// The object in the store is also used for rendering so return a copy
return ve.copyArray( converter.getStore().value( index ) );
} else {
span = doc.createElement( 'span' );
// All we need to send back to Parsoid is the original template marker,
// with a reconstructed data-mw property.
span.setAttribute( 'typeof', 'mw:Object/Template' );
span.setAttribute( 'data-mw', JSON.stringify( dataElement.attributes.mw ) );
return [ span ];
}
};
/* Concrete subclasses */
/**
* DataModel MediaWiki template block node.
*
* @class
* @extends ve.dm.MWTemplateNode
* @constructor
* @param {number} [length] Length of content data in document; ignored and overridden to 0
* @param {Object} [element] Reference to element in linear model
*/
ve.dm.MWTemplateBlockNode = function VeDmMWTemplateBlockNode( length, element ) {
// Parent constructor
ve.dm.MWTemplateNode.call( this, length, element );
};
ve.inheritClass( ve.dm.MWTemplateBlockNode, ve.dm.MWTemplateNode );
ve.dm.MWTemplateBlockNode.static.matchTagNames = [];
ve.dm.MWTemplateBlockNode.static.name = 'MWtemplateBlock';
/**
* DataModel MediaWiki template inline node.
*
* @class
* @extends ve.dm.MWTemplateNode
* @constructor
* @param {number} [length] Length of content data in document; ignored and overridden to 0
* @param {Object} [element] Reference to element in linear model
*/
ve.dm.MWTemplateInlineNode = function VeDmMWTemplateInlineNode( length, element ) {
// Parent constructor
ve.dm.MWTemplateNode.call( this, length, element );
};
ve.inheritClass( ve.dm.MWTemplateInlineNode, ve.dm.MWTemplateNode );
ve.dm.MWTemplateInlineNode.static.matchTagNames = [];
ve.dm.MWTemplateInlineNode.static.name = 'MWtemplateInline';
ve.dm.MWTemplateInlineNode.static.isContent = true;
/* Registration */
ve.dm.modelRegistry.register( ve.dm.MWTemplateNode );
ve.dm.modelRegistry.register( ve.dm.MWTemplateBlockNode );
ve.dm.modelRegistry.register( ve.dm.MWTemplateInlineNode );