diff --git a/modules/ve/ce/nodes/ve.ce.AlienBlockNode.js b/modules/ve/ce/nodes/ve.ce.AlienBlockNode.js index d5ccf8cef2..a3b4389e1a 100644 --- a/modules/ve/ce/nodes/ve.ce.AlienBlockNode.js +++ b/modules/ve/ce/nodes/ve.ce.AlienBlockNode.js @@ -24,6 +24,7 @@ ve.ce.AlienBlockNode = function VeCeAlienBlockNode( model ) { // Events this.model.addListenerMethod( this, 'update', 'onUpdate' ); this.$.on( 'mouseenter', ve.bind( this.onMouseEnter, this ) ); + this.addListenerMethod( this, 'live', 'onLive' ); // Initialization this.onUpdate(); @@ -48,21 +49,26 @@ ve.ce.AlienBlockNode.rules = { /* Methods */ -ve.ce.AlienBlockNode.prototype.onUpdate = function () { - var $shieldTemplate = this.constructor.static.$shieldTemplate; - this.$.html( this.model.getAttribute( 'html' ) ); - this.$.add( this.$.find( '*' ) ).each( function () { - var $this = $( this ); - if ( this.nodeType === Node.ELEMENT_NODE ) { - if ( - ( $this.css( 'float' ) === 'none' || $this.css( 'float' ) === '' ) && - !$this.hasClass( 've-ce-alienBlockNode' ) - ) { - return; +ve.ce.AlienBlockNode.prototype.onLive = function (live) { + if( this.live === true ) { + var $shieldTemplate = this.constructor.static.$shieldTemplate; + this.$.add( this.$.find( '*' ) ).each( function () { + var $this = $( this ); + if ( this.nodeType === Node.ELEMENT_NODE ) { + if ( + ( $this.css( 'float' ) === 'none' || $this.css( 'float' ) === '' ) && + !$this.hasClass( 've-ce-alienBlockNode' ) + ) { + return; + } + $this.append( $shieldTemplate.clone() ); } - $this.append( $shieldTemplate.clone() ); - } - } ); + } ); + } +}; + +ve.ce.AlienBlockNode.prototype.onUpdate = function () { + this.$.html( this.model.getAttribute( 'html' ) ); }; ve.ce.AlienBlockNode.prototype.onMouseEnter = function () { diff --git a/modules/ve/ce/ve.ce.BranchNode.js b/modules/ve/ce/ve.ce.BranchNode.js index 25991e9d59..6904396461 100644 --- a/modules/ve/ce/ve.ce.BranchNode.js +++ b/modules/ve/ce/ve.ce.BranchNode.js @@ -167,6 +167,7 @@ ve.ce.BranchNode.prototype.onSplice = function ( index ) { removals[i].detach(); // Update DOM removals[i].$.detach(); + removals[i].setLive( false ); } if ( args.length >= 3 ) { if ( index ) { @@ -180,6 +181,9 @@ ve.ce.BranchNode.prototype.onSplice = function ( index ) { } else { this.$.prepend( args[i].$ ); } + if ( this.live !== args[i].isLive() ) { + args[i].setLive( this.live ); + } } } @@ -251,3 +255,14 @@ ve.ce.BranchNode.prototype.clean = function () { } this.setupSlugs(); }; + +/** + * @method + */ +ve.ce.BranchNode.prototype.setLive = function ( live ) { + this.live = live; + this.emit( 'live' ); + for ( var i = 0; i < this.children.length; i++ ) { + this.children[i].setLive( live ); + } +}; \ No newline at end of file diff --git a/modules/ve/ce/ve.ce.Node.js b/modules/ve/ce/ve.ce.Node.js index 1ddc78f787..900373549a 100644 --- a/modules/ve/ce/ve.ce.Node.js +++ b/modules/ve/ce/ve.ce.Node.js @@ -24,6 +24,8 @@ ve.ce.Node = function VeCeNode( type, model, $element ) { this.model = model; this.$ = $element || $( '
' ); this.parent = null; + // Holds the information about whether or not the node is attached to the live DOM + this.live = false; this.$.data( 'node', this ); @@ -231,3 +233,19 @@ ve.ce.Node.getSplitableNode = function ( node ) { return splitableNode; }; + +/** + * @method + * @returns {Boolean} Node is attached to the live DOM + */ +ve.ce.Node.prototype.isLive = function () { + return this.live; +}; + +/** + * @method + */ +ve.ce.Node.prototype.setLive = function ( live ) { + this.live = live; + this.emit( 'live' ); +}; \ No newline at end of file diff --git a/modules/ve/ve.Surface.js b/modules/ve/ve.Surface.js index b806b4019d..83e745d03f 100644 --- a/modules/ve/ve.Surface.js +++ b/modules/ve/ve.Surface.js @@ -39,6 +39,8 @@ ve.Surface = function VeSurface( parent, dom, options ) { ); // Initialization + // Propagate to each node information that it is live (attached to the live DOM) + this.view.getDocument().getDocumentNode().setLive( true ); this.setupToolbars(); this.setupCommands(); ve.instances.push( this );