mediawiki-extensions-Visual.../modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
Catrope 4ce69758cc Fix freaky disappearance of template nodes
ce.GeneratedContentNode had an interesting bug where it called .append()
directly on DOM elements stored in the store. They weren't cloned,
which meant the previous rendering of the same node would just disappear,
and they also weren't adopted into the correct document which would
probably have caused other issues as well.

Properly clone and transplant the nodes from the store before attaching
them to the DOM.

Change-Id: I423db85cb7c3851a9bf68de03c72aa22994d9474
2013-06-07 00:06:23 +00:00

95 lines
2.3 KiB
JavaScript

/*!
* VisualEditor ContentEditable GeneratedContentNode class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* ContentEditable generated content node.
*
* @class
* @abstract
*
* @constructor
*/
ve.ce.GeneratedContentNode = function VeCeGeneratedContentNode() {
// DOM Changes
this.$.addClass( 've-ce-generatedContentNode' );
this.$.attr( 'contenteditable', false );
// Events
this.model.connect( this, { 'update': 'onUpdate' } );
// Initialization
this.onUpdate();
};
/* Methods */
/**
* Handle update events.
*
* @method
*/
ve.ce.GeneratedContentNode.prototype.onUpdate = function () {
var doc = this.getElementDocument(),
store = this.model.doc.getStore(),
index = store.indexOfHash( ve.getHash( this.model ) );
if ( index !== null ) {
if ( this.live ) {
this.emit( 'teardown' );
}
this.$.empty().append(
this.$$( store.value( index ) ).map( function ( i, domElement ) {
return doc.importNode( domElement, true );
} )
);
if ( this.live ) {
this.emit( 'setup' );
}
} else {
this.startGenerating();
this.generateContents()
.done( ve.bind( this.doneGenerating, this ) )
.fail( ve.bind( this.failGenerating, this ) );
}
};
/**
* Start a deferred process to generate the contents of the node.
* @returns {jQuery.Promise} Promise object
*/
ve.ce.GeneratedContentNode.prototype.generateContents = function () {
throw new Error( 've.ce.GeneratedContentNode subclass must implement generateContents' );
};
/**
* Called when the node starts generating new content.
* @method
*/
ve.ce.GeneratedContentNode.prototype.startGenerating = function () {
// TODO: add 'generating' style
};
/**
* Called when the node successfully finishes generating new content.
*
* @method
* @param {HTMLElement[]} domElements Generated content
*/
ve.ce.GeneratedContentNode.prototype.doneGenerating = function ( domElements ) {
var store = this.model.doc.getStore(),
hash = ve.getHash( this.model );
store.index( domElements, hash );
// TODO: remove 'generating' style
this.onUpdate();
};
/**
* Called when the has failed to generate new content.
* @method
*/
ve.ce.GeneratedContentNode.prototype.failGenerating = function () {
// TODO: remove 'generating' style
};